/* A tiley map editor for general use */
/* Started 28/9/97 by Robin Burrows (C)1997 */
/* This version 1.23 released ???? (C)2001 */
/* Feel free to alter or use pieces of this for anything you like, but if you use a */
/* substantial portion, you MUST give me a credit in whatever you used it for. */

/* See readsrctxt for more info. */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#define MAPVERH 1
#define MAPVERL 0
#define BKDTMEM (32768*32)
#define ANDTMEM (65536*4)
#define ABUFMEM (2048*8)
#define BKGFXMEM (1048576*8)
#define BLOCKSTRSIZE 32
#define MAXBRSH 16

#define ER_NONE 0
#define ER_MAPLOADERROR 1
#define ER_TOOMANYPAR 2
#define ER_MAPTOONEW 3
#define ER_OUTOFMEM 4
#define ER_NOOPEN 5
#define ER_MAPSAVEERROR 6

#define AN_END -1
#define AN_NONE 0
#define AN_LOOPF 1
#define AN_LOOPR 2
#define AN_ONCE 3
#define AN_ONCEH 4
#define AN_PPFF 5
#define AN_PPRR 6
#define AN_PPRF 7
#define AN_PPFR 8
#define AN_ONCES 9

/* Prototypes (Is that what they're called?) */
void DrawTheMap (void);
void ShowCoords (void);
void RenderBlockIcons (void);
void ShowBlockGfxGraphics (int, int, int);

typedef struct {	/* Structure for data blocks */
long int bgoff, fgoff;	/* offsets from start of graphic blocks */
long int fgoff2, fgoff3; /* more overlay blocks */
unsigned long int user1, user2;	/* user long data */
unsigned short int user3, user4;	/* user short data */
unsigned char user5, user6, user7;	/* user byte data */
unsigned char tl : 1;	/* bits for collision detection */
unsigned char tr : 1;
unsigned char bl : 1;
unsigned char br : 1;
unsigned char trigger : 1;	/* bit to trigger an event */
unsigned char unused1 : 1;
unsigned char unused2 : 1;
unsigned char unused3 : 1;
} BLKSTR;

typedef struct { /* Animation control structure */
signed char antype;	/* Type of anim, AN_? */
signed char andelay;	/* Frames to go before next frame */
signed char ancount;	/* Counter, decs each frame, till 0, then resets to andelay */
signed char anuser;	/* User info */
long int ancuroff;	/* Points to current offset in list */
long int anstartoff;	/* Points to start of blkstr offsets list, AFTER ref. blkstr offset */
long int anendoff;	/* Points to end of blkstr offsets list */
} ANISTR;

typedef struct {	/* Generic structure for chunk headers */
char id1, id2, id3, id4;	/* 4 byte header id. */
long int headsize;		/* size of header chunk. */
} GENHEAD;

typedef struct {	/* Map header structure */
/* char M,P,H,D;	4 byte chunk identification. */
/* long int mphdsize;	size of map header. */
char mapverhigh;	/* map version number to left of . (ie X.0). */
char mapverlow;		/* map version number to right of . (ie 0.X). */
char lsb;		/* if 1, data stored LSB first, otherwise MSB first. */
char maptype;	/* 0 for 32 offset still, -16 offset anim shorts in BODY added FMP0.5*/
short int mapwidth;	/* width in blocks. */
short int mapheight;	/* height in blocks. */
short int reserved1;
short int reserved2;
short int blockwidth;	/* width of a block (tile) in pixels. */
short int blockheight;	/* height of a block (tile) in pixels. */
short int blockdepth;	/* depth of a block (tile) in planes (ie. 256 colours is 8) */
short int blockstrsize;	/* size of a block data structure */
short int numblockstr;	/* Number of block structures in BKDT */
short int numblockgfx;	/* Number of 'blocks' in graphics (BODY) */
unsigned char ckey8bit, ckeyred, ckeygreen, ckeyblue; /* colour key values added FMP0.4*/
/* info for non rectangular block maps added FMP0.5*/
short int blockgapx, blockgapy, blockstaggerx, blockstaggery;
short int clickmask, pillars;
} MPHD;

typedef struct {	/* Editor prefs structure */
/* char E,D,H,D;	4 byte chunk identification. */
/* long int edhdsize;	size of editor header. */
short int xmapoffset;	/* editor offset, in blocks, from left. */
short int ymapoffset;	/* editor offset, in blocks, from right. */
long int fgcolour;	/* fg colour for text, buttons etc. */
long int bgcolour;	/* bg colour for text, buttons etc. */
short int swidth;		/* width of current screen res */
short int sheight;	/* height of current screen res */
short int strtstr;	/* first structure in view */
short int strtblk;	/* first block graphic in view */
short int curstr;		/* current block structure */
short int curanim;	/* current anim structure */
short int animspd;	/* gap in frames between anims */
short int span;		/* control panel height */
short int numbrushes;	/* number of brushes to follow. */
short int pad;
} EDHD;

typedef struct { /* Info for MapFill function */
short int leftedge, width, yoff;
} MAPFILL;

unsigned char trans16hi, trans16low, transred, transgreen, transblue, trans8bit;
short int sheight, swidth, sdepth, merror, mapwidth, mapheight, strtstr, strtblk, strtanim;
short int blockwidth, blockheight, blockdepth, blockstrsize, animspd, gridon, zoomon, maplayer;
short int xmapoffset, ymapoffset, span, numblockstr, numblockgfx, numblockanim, numbrushes;
short int curstr, curanim, oldxoff, oldyoff, oldblockx, oldblocky, curbrsh, revealanims, pastebrushnt;
long int bgcolour, fgcolour, curplacetile;
/* new for V1.23 */
int mapislsb, maptype;
int blockgapx, blockgapy, blockstaggerx, blockstaggery;
int clickmask, picklayer, picklx, pickly;
char * altgfxpt = NULL;
char novctext[70];
char mapfilename[256];
char gfxfilename[256];
FILE *filept;
GENHEAD genheader;
unsigned char *chunklist = NULL;
int isopillars = 0, isoreveal = 0, flippedtiles = 0;

short int * mappt = NULL;
char * blockgfxpt = NULL;
char * blockstrpt = NULL;
char * animstrpt = NULL;
unsigned char * cmappt = NULL;
short int * brshpt[MAXBRSH]= {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
char brshname[MAXBRSH][64]= {
"Brush", "Brush", "Brush", "Brush",
"Brush", "Brush", "Brush", "Brush",
"Brush", "Brush", "Brush", "Brush",
"Brush", "Brush", "Brush", "Brush" };
short int * mapmappt[8]={ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };

int mapaltered;

char *errorstring[] = {
"No error",
"Couldn't load map file (missing, corrupt or not a map file?)",
"Usage: Mappy or Mappy [mapfile]",
"Map file too new, get a newer version of this editor",
"Out of memory!",
"Can't open file, invalid filename?",
"Couldn't save map file (out of disk space, or empty map?)"
};

char *eybs = "Please edit your block structure XXXX";

char authorname[70];
char authorinfo1[70];
char authorinfo2[70];
char authorinfo3[70];
char bwidths[16];
char bheights[16];
char mwidths[16];
char mheights[16];
char bslong1[10];
char bslong2[10];
char bsword1[6];
char bsword2[6];
char bsbyte1[4];
char bsbyte2[4];
char bsbyte3[4];

char mynull [2] = { 0, 0 };

BLKSTR blkbuffer;
char * animbufferpt;

//FILE * dbgfpt = NULL;
//pragma warn -sig
int logit (char * str, ...)
{

	return 0;
/*
va_list argptr;
int cnt = 0;

	va_start(argptr, str);
	if (dbgfpt != NULL)
		cnt = vfprintf(dbgfpt, str, argptr);
	va_end(argptr);
	fflush (dbgfpt);

	return(cnt);
*/
}

void InsertBytes (char * inpt, char * endpt, int amount)
{
char * endpt2 = endpt;
	endpt2 -= amount;
	while (endpt2!=inpt) { endpt--; endpt2--; *endpt = *endpt2; }
	while (amount) { *endpt2 = 0; endpt2++; amount--; }
}

void RemoveBytes (char * inpt, char * endpt, int amount)
{
char * inpt2 = inpt;
	inpt2 += amount;
	while (inpt2!=endpt) { *inpt = *inpt2; inpt++; inpt2++; }
}

void InsertBytesR (char * inpt, char * endpt, int amount)
{
char * inpt2 = inpt;
	inpt2 += amount;
	while (inpt2!=endpt) { *inpt = *inpt2; inpt++; inpt2++; }
	while (amount) { *inpt = 0; inpt++; amount--; }
}

void RemoveBytesR (char * inpt, char * endpt, int amount)
{
char * endpt2 = endpt;
	endpt2 -= amount;
	while (endpt2!=inpt) { endpt--; endpt2--; *endpt = *endpt2; }
}
unsigned long int byteswapl (unsigned long int i)
{
unsigned long int j;
	j = i&0xFF; j <<= 8; i >>= 8; j |= i&0xFF; j <<= 8; i >>= 8;
	j |= i&0xFF; j <<= 8; i >>= 8; j |= i&0xFF; return j;
}

unsigned short int byteswaps (unsigned short int i)
{
unsigned short int j;
	j = i&0xFF; j <<= 8; i >>= 8; j |= i&0xFF; return j;
}

void SetTranspColour (void)
{
	switch (blockdepth) {
		case 15:
			trans16hi = ((transred>>1)&0x7C)|((transgreen>>6)&0x03);
			trans16low = ((transgreen<<2)&0xE0)|((transblue>>3)&0x1F);
			break;
		case 16:
			trans16hi = (transred&0xF8)|((transgreen>>5)&0x07);
			trans16low = ((transgreen<<3)&0xE0)|((transblue>>3)&0x1F);
			break;
		default:
			trans16hi = 0; trans16low = 0;
         break;
	}
}

char * GetBrushName (int bnum)
{
	return brshname[bnum];
}

short int * GetLayerpt (int layernum)
{
	return mapmappt[layernum];
}

int PickLayer (void)
{
int i;

	if (mapmappt[picklayer]==NULL) return -1;
	mappt = mapmappt[picklayer];
	i = maplayer; maplayer = picklayer;	picklayer = i;
	i = picklx; picklx = xmapoffset; xmapoffset = i;
	i = pickly; pickly = ymapoffset; ymapoffset = i;
	return 0;
}

int ChangeLayer (int newlayer)
{
	if (mapmappt[newlayer]==NULL) return -1;
	mappt = mapmappt[newlayer]; maplayer = newlayer;
	return 0;
}

int DeleteMapLayer (void)
{
int i;

	if (maplayer==0 && mapmappt[1]==NULL) return -1;
	if (mapmappt[maplayer]!=NULL) free (mapmappt[maplayer]);
	for (i=maplayer;i<7;i++) mapmappt[i] = mapmappt[i+1];
	mapmappt[7] = NULL;
	if (maplayer>0) maplayer--;
	mappt = mapmappt[maplayer];
	return maplayer;
}

int CreateMapLayer (void)
{
int i;

	if (mapmappt[7]!=NULL) return -1;
	maplayer++;
	for (i=7;i>maplayer;i--) mapmappt[i] = mapmappt[i-1];
	mapmappt[maplayer] = (short int *) malloc (mapwidth*mapheight*2);
	if (mapmappt[maplayer]==NULL) return -1;
	else { memset (mapmappt[maplayer], 0, mapwidth*mapheight*2); return maplayer; }
}

void FreeAll (void)
{
int i;
unsigned char * temppt;

	mapaltered = 0;
	if (blockgfxpt!=NULL) { free (blockgfxpt); blockgfxpt = NULL; }
	if (altgfxpt!=NULL) { free (altgfxpt); altgfxpt = NULL; }
	if (blockstrpt!=NULL) { free (blockstrpt); blockstrpt = NULL; }
	if (animstrpt!=NULL) { free (animstrpt); animstrpt = NULL; }
	if (cmappt!=NULL) { free (cmappt); cmappt = NULL; }
	for (i=0;i<8;i++)
	{
		if (mapmappt[i]!=NULL) { free (mapmappt[i]); mapmappt[i] = NULL; }
	}
	mappt = NULL;

	if (animbufferpt!=NULL) { free (animbufferpt); animbufferpt = NULL; }
	for (i=0;i<MAXBRSH;i++)
	{
		if (brshpt[i]!=NULL) { free (brshpt[i]); brshpt[i] = NULL; }
		strcpy (brshname[i], "Brush");
	}

	while (chunklist!=NULL) {
		temppt = *((unsigned char **) chunklist);
		free (chunklist);
		chunklist = temppt;
	}

	curstr = 0; numblockstr = 0; numblockgfx = 0;
	curbrsh = 0; numbrushes = 0; mapwidth = 0; mapheight = 0; strtanim = 0;
	maptype = 0;
	blockwidth = 0; blockheight = 0; blockdepth = 0; blockstrsize = BLOCKSTRSIZE;
	fgcolour = 255; bgcolour = 0; curanim = -1; animspd = 0; numblockanim = 0;
	maplayer = 0; authorname[0] = 0; xmapoffset = 0; ymapoffset = 0;
	swidth = 640; sheight = 480; span = 32; strtstr = 0; strtblk = 0;
	authorinfo1[0] = 0; authorinfo2[0] = 0; authorinfo3[0] = 0;
	novctext[0] = 0;
	blockgapx = 0; blockgapy = 0; blockstaggerx = 0; blockstaggery = 0;
	clickmask = 0;

	return;
}

int CreateNewMap (int newmw, int newmh, int newmd, int newbw, int newbh, int newbgx, int newbgy, int newbsx, int newbsy, int newmt)
{
	FreeAll ();

	cmappt = (unsigned char *) malloc (3*256);
	if (cmappt==NULL) return -1;
	*cmappt=0; *(cmappt+1)=0; *(cmappt+2)=0;
	*(cmappt+(256*3)-3)=255; *(cmappt+(256*3)-2)=255; *(cmappt+(256*3)-1)=255;

	blockgfxpt = (void *) malloc (BKGFXMEM);
	if (blockgfxpt==NULL) return -1;
	blockstrpt = (void *) malloc (BKDTMEM);
	if (blockstrpt==NULL) return -1;
	mappt = (short int *) malloc (newmw*newmh*2);
	if (mappt==NULL) return -1;
	mapmappt[0] = mappt; maplayer = 0;

	if (newmd==15) memset (blockgfxpt, 0, (newbw*newbh*2));
	else memset (blockgfxpt, 0, (newbw*newbh*(newmd/8)));

	memset (blockstrpt, 0, BLOCKSTRSIZE);
//	memset (animstrpt, 0, ANDTMEM); *(animstrpt+ANDTMEM-sizeof(ANISTR))=-1;
	memset ((char *) mappt, 0, (newmw*newmh*2));

	*(blockstrpt+BLOCKSTRSIZE)=-1;
	*(blockstrpt+BLOCKSTRSIZE+1)=-1;
//	*(animstrpt+ANDTMEM-sizeof(ANISTR))=-1;

	numblockgfx=1; numblockstr=1; strtstr=0; strtblk=0;
	curstr=0; curanim=-1; xmapoffset = 0; ymapoffset = 0;
	mapwidth = newmw; mapheight = newmh; blockwidth = newbw; blockheight = newbh;
	swidth = 640; sheight = 480; sdepth = newmd;
	blockdepth = sdepth; fgcolour = 255, bgcolour = 0;
	if (sdepth==15) fgcolour = 0x7fff;
	if (sdepth==16) fgcolour = 0xffff;
	if (sdepth==24) fgcolour = 0xffffff;
	if (sdepth==32) fgcolour = 0xffffff;
	blockgapx = newbgx; blockgapy = newbgy;
	blockstaggerx = newbsx; blockstaggery = newbsy;
	maptype = newmt; mapislsb = 1;

	mapfilename[0] = 0;
	SetTranspColour ();
	return 0;
}

void InitAnims (void)
{
ANISTR * myanpt;
	if (animstrpt==NULL) return;
	numblockanim = 0;
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=AN_END)
	{
		numblockanim++;

		if (myanpt->antype==AN_PPFR) myanpt->antype = AN_PPFF;
		if (myanpt->antype==AN_PPRF) myanpt->antype = AN_PPRR;
		if (myanpt->antype==AN_ONCES) myanpt->antype = AN_ONCE;
		if ((myanpt->antype==AN_LOOPR) || (myanpt->antype==AN_PPRR))
		{
		myanpt->ancuroff = myanpt->anstartoff;
		if ((myanpt->anstartoff)!=(myanpt->anendoff)) myanpt->ancuroff=(myanpt->anendoff)-4;
		} else {
		myanpt->ancuroff = myanpt->anstartoff;
		}
		myanpt->ancount = myanpt->andelay;
		myanpt--;
	}
}

void UpdateAnims (void)
{
ANISTR * myanpt;

	if (animstrpt==NULL) return;
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=-1)
	{
		if (myanpt->antype!=AN_NONE) { myanpt->ancount--; if (myanpt->ancount<0) {
		myanpt->ancount = myanpt->andelay;
		if (myanpt->antype==AN_LOOPF)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff+=4;
			if (myanpt->ancuroff==myanpt->anendoff) myanpt->ancuroff = myanpt->anstartoff;
		} }
		if (myanpt->antype==AN_LOOPR)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff-=4;
			if (myanpt->ancuroff==((myanpt->anstartoff)-4))
				myanpt->ancuroff = (myanpt->anendoff)-4;
		} }
		if (myanpt->antype==AN_ONCE)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff+=4;
			if (myanpt->ancuroff==myanpt->anendoff) { myanpt->antype = AN_ONCES;
				myanpt->ancuroff = myanpt->anstartoff; }
		} }
		if (myanpt->antype==AN_ONCEH)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) {
			if (myanpt->ancuroff!=((myanpt->anendoff)-4)) myanpt->ancuroff+=4;
		} }
		if (myanpt->antype==AN_PPFF)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff+=4;
			if (myanpt->ancuroff==myanpt->anendoff) { myanpt->ancuroff -= 8;
			myanpt->antype = AN_PPFR;
			if (myanpt->ancuroff<myanpt->anstartoff) myanpt->ancuroff +=4; }
		} } else {
		if (myanpt->antype==AN_PPFR)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff-=4;
			if (myanpt->ancuroff==((myanpt->anstartoff)-4)) { myanpt->ancuroff += 8;
			myanpt->antype = AN_PPFF;
			if (myanpt->ancuroff>myanpt->anendoff) myanpt->ancuroff -=4; }
		} } }
		if (myanpt->antype==AN_PPRR)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff-=4;
			if (myanpt->ancuroff==((myanpt->anstartoff)-4)) { myanpt->ancuroff += 8;
			myanpt->antype = AN_PPRF;
			if (myanpt->ancuroff>myanpt->anendoff) myanpt->ancuroff -=4; }
		} } else {
		if (myanpt->antype==AN_PPRF)
		{
			if (myanpt->anstartoff!=myanpt->anendoff) { myanpt->ancuroff+=4;
			if (myanpt->ancuroff==myanpt->anendoff) { myanpt->ancuroff -= 8;
			myanpt->antype = AN_PPRR;
			if (myanpt->ancuroff<myanpt->anstartoff) myanpt->ancuroff +=4; }
		} } }
	} } myanpt--; }
}

int MapGetchksz (unsigned char * locpt)
{
	return ((((int) (locpt[0]))<<24)|(((int) (locpt[1]))<<16)|
		(((int) (locpt[2]))<<8)|((int) (locpt[3])));
}

void MapPutshort (unsigned char * locpt, int shrt)
{
	if (mapislsb) {
		locpt[0] = (unsigned char) ((shrt)&0xFF);
		locpt[1] = (unsigned char) ((shrt>>8)&0xFF);
	} else {
		locpt[0] = (unsigned char) ((shrt>>8)&0xFF);
		locpt[1] = (unsigned char) ((shrt)&0xFF);
	}
}

void MapPutlong (unsigned char * locpt, int lng)
{
	if (mapislsb) {
		locpt[0] = (unsigned char) ((lng)&0xFF);
		locpt[1] = (unsigned char) ((lng>>8)&0xFF);
		locpt[2] = (unsigned char) ((lng>>16)&0xFF);
		locpt[3] = (unsigned char) ((lng>>24)&0xFF);
	} else {
		locpt[0] = (unsigned char) ((lng>>24)&0xFF);
		locpt[1] = (unsigned char) ((lng>>16)&0xFF);
		locpt[2] = (unsigned char) ((lng>>8)&0xFF);
		locpt[3] = (unsigned char) ((lng)&0xFF);
	}
}

int MapGetshort (unsigned char * locpt)
{
int rval;

	if (mapislsb)
	rval = ((((int) (locpt[1]))<<8)|((int) (locpt[0])));
	else
	rval = ((((int) (locpt[0]))<<8)|((int) (locpt[1])));
	if (rval & 0x8000) rval -= 0x10000;
   return rval;
}

int MapGetlong (unsigned char * locpt)
{
	if (mapislsb)
	return ((((int) (locpt[3]))<<24)|(((int) (locpt[2]))<<16)|
		(((int) (locpt[1]))<<8)|((int) (locpt[0])));
	else
	return ((((int) (locpt[0]))<<24)|(((int) (locpt[1]))<<16)|
		(((int) (locpt[2]))<<8)|((int) (locpt[3])));
}

int DecodeMPHD (unsigned char * mdatpt)
{
	logit ("MPHD: %d bytes.\n", MapGetchksz (mdatpt+4));

	mdatpt += 8;
	if (mdatpt[0] > 1) { merror = ER_MAPTOONEW; return -1; }
	if (mdatpt[2] == 1) mapislsb = 1; else mapislsb = 0;

	maptype = (int) mdatpt[3];
	logit ("Maptype=%d\n", maptype);
	if (maptype > 3) { merror = ER_MAPTOONEW; return -1; }
	mapwidth = (short) MapGetshort (mdatpt+4);
	mapheight = (short) MapGetshort (mdatpt+6);
	blockwidth = (short) MapGetshort (mdatpt+12);
	blockheight = (short) MapGetshort (mdatpt+14);
	blockdepth = (short) MapGetshort (mdatpt+16);
	blockstrsize = (short) MapGetshort (mdatpt+18);
	numblockstr = (short) MapGetshort (mdatpt+20);
	numblockgfx = (short) MapGetshort (mdatpt+22);

	if (MapGetchksz (mdatpt-4) > 24) {
		transred = mdatpt[25];
		transgreen = mdatpt[26];
		transblue = mdatpt[27];
		trans8bit = mdatpt[24];
		if (blockdepth > 8) SetTranspColour ();
	}
	if (MapGetchksz (mdatpt-4) > 28) {
		blockgapx = (int) MapGetshort (mdatpt+28);
		blockgapy = (int) MapGetshort (mdatpt+30);
		blockstaggerx = (int) MapGetshort (mdatpt+32);
		blockstaggery = (int) MapGetshort (mdatpt+34);
	} else {
		blockgapx = (int) blockwidth;
		blockgapy = (int) blockheight;
		blockstaggerx = 0;
		blockstaggery = 0;
	}
	if (MapGetchksz (mdatpt-4) > 36) clickmask = (short) MapGetshort (mdatpt+36);
	else clickmask = 0;
	if (MapGetchksz (mdatpt-4) > 38) isopillars = (short) MapGetshort (mdatpt+38);
	else isopillars = 0;

	logit ("mapwidth=%d\nmapheight=%d\nblockwidth=%d\nblockheight=%d\nblockdepth=%d\nblockstrsize=%d\nnumblockstr=%d\nnumblockgfx=%d\n",
		mapwidth, mapheight, blockwidth, blockheight, blockdepth, blockstrsize, numblockstr, numblockgfx);

	return 0;
}

int DecodeEDHD (unsigned char * mdatpt)
{
int i, j, k;
unsigned char * mybrshpt;
short int * mybrsh2pt;
char * mynamept;

	logit ("EDHD: %d bytes.\n", MapGetchksz (mdatpt+4));
	mdatpt += 8;
	xmapoffset = (short) MapGetshort (mdatpt);
	ymapoffset = (short) MapGetshort (mdatpt+2);
	fgcolour = (int) MapGetlong (mdatpt+4);
	bgcolour = (int) MapGetlong (mdatpt+8);
	swidth = (short) MapGetshort (mdatpt+12);
	sheight = (short) MapGetshort (mdatpt+14);
	strtstr = (short) MapGetshort (mdatpt+16);
	strtblk = (short) MapGetshort (mdatpt+18);
	curstr = (short) MapGetshort (mdatpt+20);
	curanim = (short) MapGetshort (mdatpt+22); curanim = -1;
	animspd = (short) MapGetshort (mdatpt+24);
	span = (short) MapGetshort (mdatpt+26);
	numbrushes = (short) MapGetshort (mdatpt+28);
	curbrsh = 0;
	if (clickmask == 0) {
		clickmask = (int) MapGetshort (mdatpt+30);
		if (clickmask<0 || clickmask >= numblockgfx) clickmask = 0;
	}

	if (numbrushes>0)
	{
	mybrshpt = (mdatpt+32);
		for (i=0;i<8;i++)
		{
			j = MapGetshort (mybrshpt); j *= MapGetshort (mybrshpt+2); j *= 2; j += 4;
			brshpt[i] = malloc (j); j /= 2; mybrsh2pt = brshpt[i];
			*mybrsh2pt = (short) MapGetshort (mybrshpt);
			mybrsh2pt++;
			*mybrsh2pt = (short) MapGetshort (mybrshpt+2);
			mybrsh2pt++; mybrshpt+=4;
			j -= 2;
			if (maptype == 0) {
				while (j) {
					j--;
					*mybrsh2pt = (short) MapGetshort (mybrshpt);
					if (*mybrsh2pt >= 0) *mybrsh2pt /= BLOCKSTRSIZE;
					mybrsh2pt++; mybrshpt+=2;
				}
			} else {
				while (j) {
					j--;
					*mybrsh2pt = (short) MapGetshort (mybrshpt);
					if (*mybrsh2pt < 0) *mybrsh2pt *= sizeof(ANISTR);
					mybrsh2pt++; mybrshpt+=2;
				}
			}
			numbrushes--; if (!numbrushes) i=8;
		}
/* first 8 brush names */
	mynamept = (char *) mybrshpt;
	if ((MapGetchksz (mdatpt-4)) > (mynamept-((char *) mdatpt))) {
		for (i=0;i<8;i++) {
			if (brshpt[i] != NULL) {
				strcpy (brshname[i], mynamept);
				mynamept += strlen (mynamept);
				mynamept++;
			}
		}
	} else return 0;

/* more than 8 brushes */
	if (((int)mynamept)&1) mynamept++;
	mybrshpt = (unsigned char *) mynamept;
	if ((MapGetchksz (mdatpt-4)) > (((char *) mybrshpt)-((char *) mdatpt))) {
		mybrshpt += 6; k = 8+MapGetshort (mybrshpt); mybrshpt += 2;
		if (k > MAXBRSH) k = MAXBRSH;
		for (i=8;i<k;i++) {
			j = MapGetshort (mybrshpt); j *= MapGetshort (mybrshpt+2); j *= 2; j += 4;
			brshpt[i] = malloc (j); j /= 2; mybrsh2pt = brshpt[i];
			*mybrsh2pt = (short) MapGetshort (mybrshpt);
			mybrsh2pt++;
			*mybrsh2pt = (short) MapGetshort (mybrshpt+2);
			mybrsh2pt++; mybrshpt+=4;
			j -= 2;
			if (maptype == 0) {
				while (j) {
					j--;
					*mybrsh2pt = (short) MapGetshort (mybrshpt);
					if (*mybrsh2pt >= 0) *mybrsh2pt /= BLOCKSTRSIZE;
					mybrsh2pt++; mybrshpt+=2;
				}
			} else {
				while (j) {
					j--;
					*mybrsh2pt = (short) MapGetshort (mybrshpt);
					if (*mybrsh2pt < 0) *mybrsh2pt *= sizeof(ANISTR);
					mybrsh2pt++; mybrshpt+=2;
				}
			}
			strcpy (brshname[i], (char *) mybrshpt);
			mybrshpt += strlen ((char *) mybrshpt);
			mybrshpt++;
			if (((int)mybrshpt)&1) mybrshpt++;
		}
	}
	}

	logit ("xo=%d\nyo=%d\nstrtstr=%d\nstrtblk=%d\ncurstr=%d\nnumbrushes=%d\n",
		xmapoffset, ymapoffset, strtstr, strtblk, curstr, numbrushes);

	return 0;
}

int DecodeATHR (unsigned char * mdatpt)
{
int i, j;

	logit ("ATHR: %d bytes.\n", MapGetchksz (mdatpt+4));
	mdatpt += 8;
	i = 0; while (i < MapGetchksz (mdatpt-4))
	{
		authorname[i]=mdatpt[i];
		if (mdatpt[i]==0) break;
		i++;
	}
	i++; j = 0;
	while (i < MapGetchksz (mdatpt-4))
	{
		authorinfo1[j]=mdatpt[i];
		if (mdatpt[i]==0) break;
		i++; j++;
	}
	i++; j = 0;
	while (i < MapGetchksz (mdatpt-4))
	{
		authorinfo2[j]=mdatpt[i];
		if (mdatpt[i]==0) break;
		i++; j++;
	}
	i++; j = 0;
	while (i < MapGetchksz (mdatpt-4))
	{
		authorinfo3[j]=mdatpt[i];
		if (mdatpt[i]==0) break;
		i++; j++;
	}
	return 0;
}

int DecodeCMAP (unsigned char * mdatpt)
{
	logit ("CMAP: %d bytes.\n", MapGetchksz (mdatpt+4));
	mdatpt += 8;
	cmappt = (unsigned char *) malloc (MapGetchksz (mdatpt-4));
	if (cmappt==NULL) { merror = ER_OUTOFMEM; return -1; }
	memcpy (cmappt, mdatpt, MapGetchksz (mdatpt-4));
	return 0;
}

int DecodeBKDT (unsigned char * mdatpt)
{
int i, j;
BLKSTR * myblkpt;

	logit ("BKDT: %d bytes.\n", MapGetchksz (mdatpt+4));
	mdatpt += 8;
	blockstrpt = malloc (BKDTMEM);
	if (blockstrpt==NULL) { merror = ER_OUTOFMEM; return -1; }

	myblkpt = (BLKSTR *) blockstrpt;
	j = MapGetchksz (mdatpt-4);
	i = 0; while (i < j) {
		myblkpt->bgoff = (int) MapGetlong (mdatpt+i);
		myblkpt->fgoff = (int) MapGetlong (mdatpt+i+4);
		myblkpt->fgoff2 = (int) MapGetlong (mdatpt+i+8);
		myblkpt->fgoff3 = (int) MapGetlong (mdatpt+i+12);
		if (maptype > 0) {
			myblkpt->bgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			myblkpt->fgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			myblkpt->fgoff2 *= (blockwidth*blockheight*((blockdepth+1)/8));
			myblkpt->fgoff3 *= (blockwidth*blockheight*((blockdepth+1)/8));
		}
		myblkpt->user1 = (int) MapGetlong (mdatpt+i+16);
		myblkpt->user2 = (int) MapGetlong (mdatpt+i+20);
		myblkpt->user3 = (int) MapGetshort (mdatpt+i+24);
		myblkpt->user4 = (int) MapGetshort (mdatpt+i+26);
		myblkpt->user5 = mdatpt[i+28];
		myblkpt->user6 = mdatpt[i+29];
		myblkpt->user7 = mdatpt[i+30];
		if (mdatpt[i+31]&0x80) myblkpt->unused3 = 1; else myblkpt->unused3 = 0;
		if (mdatpt[i+31]&0x40) myblkpt->unused2 = 1; else myblkpt->unused2 = 0;
		if (mdatpt[i+31]&0x20) myblkpt->unused1 = 1; else myblkpt->unused1 = 0;
		if (mdatpt[i+31]&0x10) myblkpt->trigger = 1; else myblkpt->trigger = 0;
		if (mdatpt[i+31]&0x08) myblkpt->br = 1; else myblkpt->br = 0;
		if (mdatpt[i+31]&0x04) myblkpt->bl = 1; else myblkpt->bl = 0;
		if (mdatpt[i+31]&0x02) myblkpt->tr = 1; else myblkpt->tr = 0;
		if (mdatpt[i+31]&0x01) myblkpt->tl = 1; else myblkpt->tl = 0;
		i += blockstrsize;
		myblkpt++;
	}
	return 0;
}

int DecodeANDT (unsigned char * mdatpt)
{
int aniadjust;
ANISTR * myanistrpt;
unsigned char * mdatendpt;
int * myseqpt;

	logit ("ANDT: %d bytes.\n", MapGetchksz (mdatpt+4));
	mdatpt += 8;
	mdatendpt = mdatpt+MapGetchksz(mdatpt-4);

	animstrpt = malloc (ANDTMEM);
	if (animstrpt == NULL) { merror = ER_OUTOFMEM; return -1; }
	memset (animstrpt, 0, ANDTMEM);

	aniadjust = 0;
	myanistrpt = (ANISTR *) (mdatendpt);
	while (1) {
		aniadjust ++; //= (16-(sizeof(ANISTR)));
		myanistrpt--;
		if (myanistrpt->antype == AN_END) break;
	}

	logit ("Aniadjust = %d\n", aniadjust);

	myanistrpt = (ANISTR *) (animstrpt+ANDTMEM);
	while (1) {
		myanistrpt--;
		mdatendpt -= 16;
		myanistrpt->antype = mdatendpt[0];
		myanistrpt->andelay = mdatendpt[1];
		myanistrpt->ancount = mdatendpt[2];
		myanistrpt->anuser = mdatendpt[3];

		if (maptype == 0) {
		myanistrpt->ancuroff = (int) MapGetlong (mdatendpt+4)+(aniadjust*(16-sizeof(ANISTR)));
		myanistrpt->anstartoff = (int) MapGetlong (mdatendpt+8)+(aniadjust*(16-sizeof(ANISTR)));
		myanistrpt->anendoff = (int) MapGetlong (mdatendpt+12)+(aniadjust*(16-sizeof(ANISTR)));
		} else {
		myanistrpt->ancuroff = (MapGetlong(mdatendpt+4))*(sizeof(int));
		myanistrpt->ancuroff -= MapGetchksz(mdatpt-4);
		myanistrpt->anstartoff = (MapGetlong(mdatendpt+8))*(sizeof(int));
		myanistrpt->anstartoff -= MapGetchksz(mdatpt-4);
		myanistrpt->anendoff = (MapGetlong(mdatendpt+12))*(sizeof(int));
		myanistrpt->anendoff -= MapGetchksz(mdatpt-4);
		}

	logit ("anim: type=%d delay=%d count=%d cur=%d strt=%d end=%d\n",
		myanistrpt->antype, myanistrpt->andelay, myanistrpt->ancount,
      myanistrpt->ancuroff, myanistrpt->anstartoff, myanistrpt->anendoff);
		if (myanistrpt->antype == AN_END) break;
	}

	myseqpt = (int *) myanistrpt;
	while (mdatendpt > mdatpt) {
		myseqpt--;
		mdatendpt -= 4;
		if (maptype == 0)
			*myseqpt = (int) ((MapGetlong (mdatendpt)/blockstrsize)*sizeof(BLKSTR));
		else
			*myseqpt = (int) ((MapGetlong (mdatendpt))*sizeof(BLKSTR));
	}
	InitAnims ();
	return 0;
}

int DecodeAGFX (unsigned char * mdatpt)
{
	logit ("AGFX: %d bytes.\n", MapGetchksz (mdatpt+4));
	altgfxpt = malloc (MapGetchksz (mdatpt+4));
	if (altgfxpt==NULL) { merror = ER_OUTOFMEM; return -1; }
	memcpy (altgfxpt, mdatpt+8, MapGetchksz(mdatpt+4));
	return 0;
}

int DecodeBGFX (unsigned char * mdatpt)
{
	logit ("BGFX: %d bytes.\n", MapGetchksz (mdatpt+4));
	blockgfxpt = malloc (BKGFXMEM);
	if (blockgfxpt==NULL) { merror = ER_OUTOFMEM; return -1; }
	memcpy (blockgfxpt, mdatpt+8, MapGetchksz(mdatpt+4));
	return 0;
}

int DecodeNOVC (unsigned char * mdatpt)
{
	logit ("NOVC: %d bytes.\n", MapGetchksz (mdatpt+4));
	if (MapGetchksz (mdatpt+4) < 70) strcpy (novctext, (char *) mdatpt+8);
	return 0;
}

int DecodeLayer (unsigned char * mdatpt, int lnum)
{
int i, j, k, l;
short int * mymappt, * mymap2pt;

	logit ("Layer %d: %d bytes.\n", lnum, MapGetchksz (mdatpt+4));
	mapmappt[lnum] = malloc (mapwidth*mapheight*sizeof(short int));
	if (mapmappt[lnum] == NULL) { merror = ER_OUTOFMEM; return -1; }
	logit ("Maptype=%d\n", maptype);

	mdatpt += 8;
	mymappt = mapmappt[lnum];
	if (maptype == 0) {
	logit ("Maptype==0\n");
	for (j=0;j<mapheight;j++) {
		for (i=0;i<mapwidth;i++) {
			*mymappt = (short int) MapGetshort (mdatpt);
			if (*mymappt >= 0) { *mymappt /= blockstrsize; }
			else { *mymappt /= 16; *mymappt *= sizeof(ANISTR); }
			mdatpt+=2; mymappt++;
		}
	}
	} else {
	if (maptype == 1) {
	logit ("Maptype==1\n");
	for (j=0;j<mapheight;j++) {
		for (i=0;i<mapwidth;i++) {
			*mymappt = (short int) MapGetshort (mdatpt);
			logit ("%d-", *mymappt);
			if (*mymappt < 0) { *mymappt *= sizeof(ANISTR); }
			mdatpt+=2; mymappt++;
		}
		logit ("\n");
	}
	} else {
	if (maptype == 2) {
	logit ("Maptype==2\n");
	for (j=0;j<mapheight;j++) {
		logit ("\nLine %d: ", j);
		for (i=0;i<mapwidth;) {
			k = (int) MapGetshort (mdatpt);
			mdatpt += 2;
			if (k > 0) {
			logit ("%dC : ", k);
				while (k) {
					*mymappt = (short int) MapGetshort (mdatpt);
					if (*mymappt < 0) { *mymappt *= sizeof(ANISTR); }
					mymappt++; mdatpt += 2;
					i++; k--;
				}
			} else {
			if (k < 0) {
			logit ("%dR : ", k);
				l = (int) MapGetshort (mdatpt); mdatpt += 2;
				while (k) {
					*mymappt = (short int) l;
					if (*mymappt < 0) { *mymappt *= sizeof(ANISTR); }
					mymappt++;
					i++; k++;
				}
			} else {
			} }
		}
	}
	} else {
	if (maptype == 3) {
	logit ("Maptype==3\n");
	for (j=0;j<mapheight;j++) {
		for (i=0;i<mapwidth;) {
			k = (int) MapGetshort (mdatpt);
			mdatpt += 2;
			if (k > 0) {
				while (k) {
					*mymappt = (short int) MapGetshort (mdatpt);
					if (*mymappt < 0) { *mymappt *= sizeof(ANISTR); }
					mymappt++; mdatpt += 2;
					i++; k--;
				}
			} else {
			if (k < 0) {
				mymap2pt = mymappt + (int) MapGetshort (mdatpt); mdatpt += 2;
				while (k) {
					*mymappt = *mymap2pt;
					if (*mymappt < 0) { *mymappt *= sizeof(ANISTR); }
					mymappt++; mymap2pt++;
					i++; k++;
				}
			} else {
			} }
		}
	}
	} } } }

	if (lnum == 0) { mappt = mapmappt[lnum]; maplayer = 0; }
	return 0;
}

int DecodeNULL (unsigned char * mdatpt)
{
unsigned char * mynllpt, * temppt;

	logit ("UNKNOWN: %d bytes.\n", MapGetchksz (mdatpt+4));
	mynllpt = (unsigned char *) malloc (MapGetchksz(mdatpt+4)+12);
	if (mynllpt==NULL) { merror = ER_OUTOFMEM; return -1; }
	*((unsigned char **) mynllpt) = NULL;
	memcpy (mynllpt+4, mdatpt, MapGetchksz(mdatpt+4)+8);

	if (chunklist==NULL) {
		chunklist = mynllpt;
		return 0;
	}

	temppt = chunklist;
	while ((*((unsigned char**)temppt))!=NULL) temppt = *((unsigned char **) temppt);
	*((unsigned char **) temppt) = mynllpt;

	return 0;
}

int MapDecode (FILE * mfpt, int mpfilesize)
{
int chkdn;
unsigned char * fmappospt;
char mphdr[8];

	logit ("MapDecode\n");
	FreeAll ();
	logit ("After FreeAll\n");
	mpfilesize -= 12;
	while (mpfilesize > 0) {

		if (fread (mphdr, 1, 8, mfpt) != 8) {
			merror = ER_OUTOFMEM;
			FreeAll ();
			return -1;
		}
		fmappospt = malloc (MapGetchksz((unsigned char *) mphdr+4)+8);
		memcpy (fmappospt, mphdr, 8);
		if (fread (fmappospt+8, 1, MapGetchksz((unsigned char *) mphdr+4), mfpt) != MapGetchksz(mphdr+4)) {
			merror = ER_MAPLOADERROR;
			FreeAll ();
			return -1;
		}

		chkdn = 0;
		if (!strncmp ((char *) fmappospt, "ATHR", 4)) { chkdn = 1; DecodeATHR (fmappospt); }
		if (!strncmp ((char *) fmappospt, "MPHD", 4)) { chkdn = 1; DecodeMPHD (fmappospt); }
		if (!strncmp ((char *) fmappospt, "EDHD", 4)) { chkdn = 1; DecodeEDHD (fmappospt); }
		if (!strncmp ((char *) fmappospt, "CMAP", 4)) { chkdn = 1; DecodeCMAP (fmappospt); }
		if (!strncmp ((char *) fmappospt, "BKDT", 4)) { chkdn = 1; DecodeBKDT (fmappospt); }
		if (!strncmp ((char *) fmappospt, "ANDT", 4)) { chkdn = 1; DecodeANDT (fmappospt); }
		if (!strncmp ((char *) fmappospt, "AGFX", 4)) { chkdn = 1; DecodeAGFX (fmappospt); }
		if (!strncmp ((char *) fmappospt, "BGFX", 4)) { chkdn = 1; DecodeBGFX (fmappospt); }
		if (!strncmp ((char *) fmappospt, "NOVC", 4)) { chkdn = 1; DecodeNOVC (fmappospt); }
		if (!strncmp ((char *) fmappospt, "BODY", 4)) { chkdn = 1; DecodeLayer (fmappospt, 0); }
		if (!strncmp ((char *) fmappospt, "LYR1", 4)) { chkdn = 1; DecodeLayer (fmappospt, 1); }
		if (!strncmp ((char *) fmappospt, "LYR2", 4)) { chkdn = 1; DecodeLayer (fmappospt, 2); }
		if (!strncmp ((char *) fmappospt, "LYR3", 4)) { chkdn = 1; DecodeLayer (fmappospt, 3); }
		if (!strncmp ((char *) fmappospt, "LYR4", 4)) { chkdn = 1; DecodeLayer (fmappospt, 4); }
		if (!strncmp ((char *) fmappospt, "LYR5", 4)) { chkdn = 1; DecodeLayer (fmappospt, 5); }
		if (!strncmp ((char *) fmappospt, "LYR6", 4)) { chkdn = 1; DecodeLayer (fmappospt, 6); }
		if (!strncmp ((char *) fmappospt, "LYR7", 4)) { chkdn = 1; DecodeLayer (fmappospt, 7); }
		if (!chkdn) DecodeNULL (fmappospt);

		mpfilesize -= 8;
		mpfilesize -= MapGetchksz (fmappospt+4);
		free (fmappospt);
		logit ("Left = %d bytes\n", mpfilesize);

		if (merror != ER_NONE) { FreeAll (); return -1; }
	}
	SetTranspColour ();
	return 0;
}

int LoadProject (void)
{
int mretval;
FILE * fpt;
char idtag[4];
unsigned char tempc;
int mapfilesize;

//	if (dbgfpt == NULL) dbgfpt = fopen ("debug.txt", "w");
	logit ("StartDebug\n");
	merror = ER_NONE;
	fpt = fopen (mapfilename, "rb");
	if (fpt == NULL) { merror = ER_NOOPEN; return -1; }

	mapfilesize = 0;
	merror = ER_MAPLOADERROR;
	if (fread (&idtag[0], 1, 1, fpt) == 1) {
	if (fread (&idtag[1], 1, 1, fpt) == 1) {
	if (fread (&idtag[2], 1, 1, fpt) == 1) {
	if (fread (&idtag[3], 1, 1, fpt) == 1) {
	if (fread (&tempc, 1, 1, fpt) == 1) {
	mapfilesize = (((int) tempc)<<24);
	if (fread (&tempc, 1, 1, fpt) == 1) {
	mapfilesize |= (((int) tempc)<<16);
	if (fread (&tempc, 1, 1, fpt) == 1) {
	mapfilesize |= (((int) tempc)<<8);
	if (fread (&tempc, 1, 1, fpt) == 1) {
	mapfilesize |= ((int) tempc);
	mapfilesize += 8;
	if (!strncmp (idtag, "FORM", 4)) {
	if (fread (&idtag[0], 1, 1, fpt) == 1) {
	if (fread (&idtag[1], 1, 1, fpt) == 1) {
	if (fread (&idtag[2], 1, 1, fpt) == 1) {
	if (fread (&idtag[3], 1, 1, fpt) == 1) {
	if (!strncmp (idtag, "FMAP", 4)) merror = ER_NONE;
	} } } } }
	} } } } } } } }

	if (merror != ER_NONE) { fclose (fpt); return -1; }

	mretval = MapDecode (fpt, mapfilesize);
	fclose (fpt);
//	if (dbgfpt != NULL) { logit ("MapLoad done\n"); fclose (dbgfpt); dbgfpt = NULL; }
	return mretval;
}

int SizeBrushes (void)
{
int i, j, k;
short int * mybrshpt;
	j = 0; for (i=0;i<MAXBRSH;i++)
	{
		if (brshpt[i]!=NULL) {
			mybrshpt = brshpt[i];
			k = *mybrshpt; mybrshpt++; k *= *mybrshpt; j += (k*2)+4;
			if (brshname[i][0] == 0) strcpy (brshname[i], "Brush");
			j += strlen (brshname[i]); j ++;
         if (i==8) j += 8;
			if (i>7) { if (!(strlen (brshname[i])&1)) j++; }
		}
	}
	if (j&1) j++;
	return j;
}

/* RleLayer */

int RleLayer (short int * lyrpt, FILE * wpt)
{
int x, y;
short int * rlemem;
int rlepos, runlen;

	rlemem = malloc (((int) mapwidth)*((int) mapheight)*8);
	rlepos = 0;
	for (y=0;y<mapheight;y++) {
		for (x=0;x<mapwidth;) {
			runlen = 0;
			if (x >= (mapwidth-1) || lyrpt[x] != lyrpt[x+1]) {
				if (x >= (mapwidth-1)) { runlen++; x++; }
				else {
					if (x >= (mapwidth-2)) { runlen += 2; x += 2; }
					else {
						while (lyrpt[x] != lyrpt[x+1] || lyrpt[x] != lyrpt[x+2]) {
							runlen++; x++;
							if (x == mapwidth) break;
						}
					}
				}
				if (x < mapwidth) { x++; runlen++; }
				MapPutshort ((unsigned char *) (rlemem+rlepos), runlen); rlepos++;
				while (runlen) {
					MapPutshort ((unsigned char *) (rlemem+rlepos), lyrpt[x-runlen]); rlepos++;
					runlen--;
				}
			} else {
				while (lyrpt[x] == lyrpt[x+1]) {
					runlen++; x++;
					if (x == mapwidth) break;
				}
				if (x < mapwidth) { x++; runlen++; }
				MapPutshort ((unsigned char *) (rlemem+rlepos), -runlen);
				rlepos++;
				MapPutshort ((unsigned char *) (rlemem+rlepos), lyrpt[x-runlen]);
				rlepos++;
			}
		}
		lyrpt += mapwidth;
	}

	genheader.headsize = byteswapl(rlepos * sizeof (short int));
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); free (rlemem); return -1; }
	if (fwrite (rlemem, 1, rlepos*sizeof (short int), wpt) != (rlepos*sizeof (short int)))
	{ merror = ER_MAPSAVEERROR; fclose (filept); free (rlemem); return -1; }
	free (rlemem);
	return 0;
}

int SaveProject (void)
{
/* attempts to save project file name and path in mapfilename */
char backupname[128];
short exbrshinf[4];
MPHD mphdinfo;
EDHD edhdinfo;
unsigned char * unknownchunkpt;
short int * mybrshpt;
int i, j, k, l, m;
ANISTR * myanpt;
BLKSTR * mybkpt;
int * myanseqpt;

	merror = 0;

//	if (dbgfpt == NULL) dbgfpt = fopen ("debug.txt", "w");
	logit ("StartDebug\n");

	if (cmappt==NULL) merror = ER_MAPSAVEERROR;
	if (mappt==NULL) merror = ER_MAPSAVEERROR;
	if (blockstrpt==NULL) merror = ER_MAPSAVEERROR;
	if (blockgfxpt==NULL) merror = ER_MAPSAVEERROR;
	if (numblockstr==0) merror = ER_MAPSAVEERROR;
	if (numblockgfx==0) merror = ER_MAPSAVEERROR;
	if (mapfilename[0]==0) merror = ER_MAPSAVEERROR;

	if (merror) return 0;

	strcpy (backupname, mapfilename);
	j = 0; for (i=0;i<(strlen(backupname));i++) { if (backupname[i]=='.') j = i; }
	if (j) {
		backupname[j+1] = 'B'; backupname[j+2] = 'A';
		backupname[j+3] = 'K'; backupname[j+4] = 0;
	} else strcat (backupname, ".BAK");

	rename (mapfilename, backupname);

	genheader.id1='F'; genheader.id2='O'; genheader.id3='R'; genheader.id4='M';
	genheader.headsize=0;

	filept = NULL;
	filept = fopen (mapfilename, "wb");
	if (filept==NULL) { merror = ER_NOOPEN; return -1; }
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	genheader.id1='F'; genheader.id2='M'; genheader.id3='A'; genheader.id4='P';
	if (fwrite (&genheader, 1, sizeof(GENHEAD)-4, filept)!=sizeof(GENHEAD)-4)
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	if ((authorname[0]!=0) || (authorinfo1[0]!=0) || (authorinfo2[0]!=0) || (authorinfo3[0]!=0))
	{
	l = strlen (authorname); l += strlen (authorinfo1);
	l += strlen (authorinfo2); l += strlen (authorinfo3); l += 8;
	m = l%4; l -= m;
	genheader.id1='A'; genheader.id2='T'; genheader.id3='H'; genheader.id4='R';
	genheader.headsize=byteswapl(l);
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (authorname, 1, (strlen(authorname)+1), filept)!=(strlen(authorname)+1))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (authorinfo1, 1, (strlen(authorinfo1)+1), filept)!=(strlen(authorinfo1)+1))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (authorinfo2, 1, (strlen(authorinfo2)+1), filept)!=(strlen(authorinfo2)+1))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (authorinfo3, 1, (strlen(authorinfo3)+1+(4-m)), filept)!=(strlen(authorinfo3)+1+(4-m)))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	}

	genheader.id1='M'; genheader.id2='P'; genheader.id3='H'; genheader.id4='D';
	genheader.headsize=byteswapl(sizeof(MPHD));
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	if (maptype == 0) {
		mphdinfo.mapverhigh=0;
		mphdinfo.mapverlow=5;
	} else {
		mphdinfo.mapverhigh=1;
		mphdinfo.mapverlow=0;
	}
	mphdinfo.lsb=mapislsb; /* stored in INTEL format */
	mphdinfo.maptype=maptype;
	mphdinfo.mapwidth=mapwidth;
	mphdinfo.mapheight=mapheight;
	mphdinfo.reserved1=0;
	mphdinfo.reserved2=0;
	mphdinfo.blockwidth=blockwidth;
	mphdinfo.blockheight=blockheight;
	mphdinfo.blockdepth=blockdepth;
	mphdinfo.blockstrsize=BLOCKSTRSIZE;
	mphdinfo.numblockstr=numblockstr;
	mphdinfo.numblockgfx=numblockgfx;
	mphdinfo.ckeyred=transred;
	mphdinfo.ckeygreen=transgreen;
	mphdinfo.ckeyblue=transblue;
	mphdinfo.ckey8bit=trans8bit;
	mphdinfo.blockgapx=blockgapx;
	mphdinfo.blockgapy=blockgapy;
	mphdinfo.blockstaggerx=blockstaggerx;
	mphdinfo.blockstaggery=blockstaggery;
	mphdinfo.clickmask=(short int) clickmask;
	mphdinfo.pillars=(short int) isopillars;

	if (fwrite (&mphdinfo, 1, sizeof(MPHD), filept)!=sizeof(MPHD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	edhdinfo.xmapoffset=xmapoffset;
	edhdinfo.ymapoffset=ymapoffset;
	edhdinfo.fgcolour=fgcolour;
	edhdinfo.bgcolour=bgcolour;
	edhdinfo.sheight=sheight;
	edhdinfo.swidth=swidth;
	edhdinfo.strtstr=strtstr;
	edhdinfo.strtblk=strtblk;
	edhdinfo.span=32;
	edhdinfo.curstr=curstr;
	edhdinfo.curanim=curanim;
	edhdinfo.animspd=animspd;
	for (i=0;i<MAXBRSH;i++) {
		if (brshpt[i] == NULL) {
			for (k=(i+1);k<MAXBRSH;k++) {
				if (brshpt[k] != NULL) {
					brshpt[i] = brshpt[k];
					brshpt[k] = NULL;
					strcpy (brshname[i], brshname[k]);
					strcpy (brshname[k], "Brush");
               if (curbrsh == (k+1)) curbrsh = (i+1);
					break;
				}
			}
		}
	}
	numbrushes = 0; for (i=0;i<8;i++) {	if (brshpt[i] != NULL) numbrushes++; }
	edhdinfo.numbrushes=numbrushes;
	edhdinfo.pad=0;

	i = 0; if (numbrushes>0) i = SizeBrushes ();

	genheader.id1='E'; genheader.id2='D'; genheader.id3='H'; genheader.id4='D';
	genheader.headsize=byteswapl(i+sizeof(EDHD));
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	if (fwrite (&edhdinfo, 1, sizeof(EDHD), filept)!=sizeof(EDHD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	if (numbrushes>0)
	{
		for (i=0;i<8;i++)
		{
			if (brshpt[i] != NULL) {
			mybrshpt = brshpt[i];
			k = mybrshpt[0]; k *= mybrshpt[1]; j = (k*2)+4;
			if (maptype>0) {
				while (k) { k--;
					if (mybrshpt[2+k] < 0) mybrshpt[2+k] /= sizeof(ANISTR);
				}
			} else {
				while (k) { k--;
					if (mybrshpt[2+k] >= 0) mybrshpt[2+k] *= BLOCKSTRSIZE;
				}
			}
			if (fwrite (brshpt[i], 1, j, filept)!=j)
			{ merror = ER_MAPSAVEERROR; fclose (filept); }
			k = mybrshpt[0]; k *= mybrshpt[1]; j = (k*2)+4;
			if (maptype>0) {
				while (k) { k--;
					if (mybrshpt[2+k] < 0) mybrshpt[2+k] *= sizeof(ANISTR);
				}
			} else {
				while (k) { k--;
					if (mybrshpt[2+k] >= 0) mybrshpt[2+k] /= BLOCKSTRSIZE;
				}
			}
		} }
		if (merror) return -1;
		for (i=0;i<8;i++)
		{
			if (brshpt[i] != NULL) {
			if (fwrite (brshname[i], 1, (strlen (brshname[i]))+1, filept) != ((strlen (brshname[i]))+1))
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		} }
		if ((ftell (filept)) & 1) {
			i = 0; if (fwrite (&i, 1, 1, filept)!=1)
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		}

/* more than 8 brushes */
		k = 0; for (i=0;i<MAXBRSH;i++) {	if (brshpt[i] != NULL) k++; }
		if (k > 8) {
			exbrshinf[0] = 0;
			exbrshinf[1] = 0;
			exbrshinf[2] = 0;
			exbrshinf[3] = k-8;
			if (fwrite (exbrshinf, 1, 8, filept) != 8)
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		}
		for (i=8;i<MAXBRSH;i++) {
			if (brshpt[i] != NULL) {
			mybrshpt = brshpt[i];
			k = mybrshpt[0]; k *= mybrshpt[1]; j = (k*2)+4;
			if (maptype>0) {
				while (k) { k--;
					if (mybrshpt[2+k] < 0) mybrshpt[2+k] /= sizeof(ANISTR);
				}
			} else {
				while (k) { k--;
					if (mybrshpt[2+k] >= 0) mybrshpt[2+k] *= BLOCKSTRSIZE;
				}
			}
			if (fwrite (brshpt[i], 1, j, filept)!=j)
			{ merror = ER_MAPSAVEERROR; fclose (filept); }
			k = mybrshpt[0]; k *= mybrshpt[1]; j = (k*2)+4;
			if (maptype>0) {
				while (k) { k--;
					if (mybrshpt[2+k] < 0) mybrshpt[2+k] *= sizeof(ANISTR);
				}
			} else {
				while (k) { k--;
					if (mybrshpt[2+k] >= 0) mybrshpt[2+k] /= BLOCKSTRSIZE;
				}
			}
			if (fwrite (brshname[i], 1, (strlen (brshname[i]))+1, filept) != ((strlen (brshname[i]))+1))
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
			if (!(strlen (brshname[i])&1)) {
				if (fwrite ("\0", 1, 1, filept)!=1)
				{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
			}
			}
		}
	}

	genheader.id1='C'; genheader.id2='M'; genheader.id3='A'; genheader.id4='P';
	genheader.headsize=byteswapl(3*256);
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (cmappt, 1, 3*256, filept)!=3*256)
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	genheader.id1='B'; genheader.id2='K'; genheader.id3='D'; genheader.id4='T';
	genheader.headsize=byteswapl(numblockstr*BLOCKSTRSIZE);
	if (maptype > 0) {
		mybkpt = (BLKSTR *) blockstrpt;
		i = numblockstr; while (i) {
			mybkpt->bgoff /= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff /= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff2 /= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff3 /= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt++;
			i--;
		}
	}
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); }
	if (fwrite (blockstrpt, 1, numblockstr*BLOCKSTRSIZE, filept)!=numblockstr*BLOCKSTRSIZE)
	{ merror = ER_MAPSAVEERROR; fclose (filept); }
	if (maptype > 0) {
		mybkpt = (BLKSTR *) blockstrpt;
		i = numblockstr; while (i) {
			mybkpt->bgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff2 *= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt->fgoff3 *= (blockwidth*blockheight*((blockdepth+1)/8));
			mybkpt++;
			i--;
		}
	}
	if (merror) return -1;

	if (animstrpt!=NULL) {
	/* NOTE: Important to count the anims. */
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--; i = 0;
	j = 0; while (myanpt->antype!=-1) { i++; j++; myanpt--; } numblockanim = i;
	if (numblockanim) {
	InitAnims ();
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); i = 0; myanpt--;
	while (myanpt->antype!=-1) { if ((myanpt->anstartoff)<i) i = myanpt->anstartoff;
		myanpt--; }
	i -= 4;
	if (maptype > 0) {
		myanseqpt = (int *) ((animstrpt+ANDTMEM)+i);
		while (myanseqpt != ((int *) myanpt)) {
			*myanseqpt /= BLOCKSTRSIZE;
			myanseqpt++;
		}
		while (myanpt != ((ANISTR *) (animstrpt+ANDTMEM))) {
			logit ("anim c %d, s %d, e %d\n", myanpt->ancuroff, myanpt->anstartoff, myanpt->anendoff);
			myanpt->ancuroff -= i;
			myanpt->ancuroff /= sizeof(int);
			myanpt->anstartoff -= i;
			myanpt->anstartoff /= sizeof(int);
			myanpt->anendoff -= i;
			myanpt->anendoff /= sizeof(int);
			logit ("now c %d, s %d, e %d\n\n", myanpt->ancuroff, myanpt->anstartoff, myanpt->anendoff);
			myanpt++;
		}
	}

	genheader.id1='A'; genheader.id2='N'; genheader.id3='D'; genheader.id4='T';
	genheader.headsize=byteswapl(-i);
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (fwrite (animstrpt+ANDTMEM+i, 1, -i, filept)!=-i)
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

	if (maptype > 0) {
		myanseqpt = (int *) ((animstrpt+ANDTMEM)+i);
		do {
			myanpt--;
			logit ("2anim c %d, s %d, e %d\n", myanpt->ancuroff, myanpt->anstartoff, myanpt->anendoff);
			myanpt->ancuroff *= sizeof(int);
			myanpt->ancuroff += i;
			myanpt->anstartoff *= sizeof(int);
			myanpt->anstartoff += i;
			myanpt->anendoff *= sizeof(int);
			myanpt->anendoff += i;
			logit ("2now c %d, s %d, e %d\n\n", myanpt->ancuroff, myanpt->anstartoff, myanpt->anendoff);
		} while (myanpt->antype!=-1);
		while (myanseqpt != ((int *) myanpt)) {
			*myanseqpt *= BLOCKSTRSIZE;
			myanseqpt++;
		}
		if (merror) return -1;
	}
	}
	}

/* Write any data of unknown type that was loaded in previously */
	unknownchunkpt = chunklist;
	while (unknownchunkpt!=NULL) {
		if (fwrite (unknownchunkpt+4, 1, byteswapl(((unsigned long int *) unknownchunkpt)[2])+8, filept)
			!= byteswapl(((unsigned long int *) unknownchunkpt)[2])+8)
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		unknownchunkpt = *((unsigned char **) unknownchunkpt);
	}

	if (altgfxpt != NULL) {
		genheader.id1='A'; genheader.id2='G'; genheader.id3='F'; genheader.id4='X';
		if ((numblockgfx*blockheight*blockwidth)&1)
			genheader.headsize=byteswapl((numblockgfx*blockheight*blockwidth)+1);
		else
			genheader.headsize=byteswapl(numblockgfx*blockheight*blockwidth);
		if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }

		if (fwrite (altgfxpt, 1, numblockgfx*blockheight*blockwidth,
			filept)!=(numblockgfx*blockheight*blockwidth))
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		if ((numblockgfx*blockheight*blockwidth)&1)
			{
				if (fwrite (altgfxpt, 1, 1, filept)!=1)
				{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
			}
	}

	if (novctext[0] != 0) {
		genheader.id1='N'; genheader.id2='O'; genheader.id3='V'; genheader.id4='C';
		i = strlen(novctext); i++;
		if (i&1) i++;
		genheader.headsize=byteswapl(i);
		if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
		if (fwrite (novctext, 1, i, filept)!=i)
			{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	}

	genheader.id1='B'; genheader.id2='G'; genheader.id3='F'; genheader.id4='X';
	if (sdepth==15) genheader.headsize=byteswapl(numblockgfx*blockheight*blockwidth*2); else
	{
		if ((numblockgfx*blockheight*blockwidth*(blockdepth/8))&1)
			genheader.headsize=byteswapl((numblockgfx*blockheight*blockwidth*(blockdepth/8))+1);
		else
			genheader.headsize=byteswapl(numblockgfx*blockheight*blockwidth*(blockdepth/8));
	}
	if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; }
	if (sdepth==15) { if (fwrite (blockgfxpt, 1, numblockgfx*blockheight*blockwidth*2,
		filept)!=numblockgfx*blockheight*blockwidth*2)
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; } } else
	{ if (fwrite (blockgfxpt, 1, numblockgfx*blockheight*blockwidth*(blockdepth/8),
		filept)!=numblockgfx*blockheight*blockwidth*(blockdepth/8))
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; } }
	if ((numblockgfx*blockheight*blockwidth*(blockdepth/8))&1)
	{ if (fwrite (blockgfxpt, 1, 1, filept)!=1)
	{ merror = ER_MAPSAVEERROR; fclose (filept); return -1; } }

	for (i=0;i<8;i++) { if (mapmappt[i]!=NULL) {
	if (i == 0) {
		genheader.id1='B'; genheader.id2='O'; genheader.id3='D'; genheader.id4='Y';
	} else {
		genheader.id1='L'; genheader.id2='Y'; genheader.id3='R'; genheader.id4=i+48;
	}
	genheader.headsize=byteswapl(mapwidth*mapheight*2);

	if (maptype > 0) {
		j = ((int) mapwidth)*((int) mapheight);
		while (j) { j--;
			if (mapmappt[i][j] < 0) mapmappt[i][j] /= sizeof(ANISTR);
		}
	} else {
		j = ((int) mapwidth)*((int) mapheight);
		while (j) { j--;
			if (mapmappt[i][j] >= 0) mapmappt[i][j] *= BLOCKSTRSIZE;
		}
	}

	if (maptype == 2) {
		if (RleLayer (mapmappt[i], filept)) merror = ER_MAPSAVEERROR;
	} else {
		if (fwrite (&genheader, 1, sizeof(GENHEAD), filept)!=sizeof(GENHEAD))
		{ merror = ER_MAPSAVEERROR; fclose (filept); }
		if (fwrite ((char *)mapmappt[i], 1, mapwidth*mapheight*2, filept)!=mapwidth*mapheight*2)
		{ merror = ER_MAPSAVEERROR; fclose (filept); }
	}

	if (maptype > 0) {
		j = ((int) mapwidth)*((int) mapheight);
		while (j) { j--;
			if (mapmappt[i][j] < 0) mapmappt[i][j] *= sizeof(ANISTR);
		}
	} else {
		j = ((int) mapwidth)*((int) mapheight);
		while (j) { j--;
			if (mapmappt[i][j] >= 0) mapmappt[i][j] /= BLOCKSTRSIZE;
		}
	}
	if (merror) return -1;
	} }

	fseek (filept, 0, SEEK_END);
	genheader.headsize = ftell (filept); genheader.headsize -= 8;
	genheader.headsize = byteswapl(genheader.headsize);
	fseek (filept, 4, SEEK_SET);
	fwrite (&genheader.headsize, 1, sizeof(long int), filept);
	fclose (filept);
//	if (dbgfpt != NULL) { logit ("MapSave done\n"); fclose (dbgfpt); dbgfpt = NULL; }
	return 0;
}

/*
void DrawBlock (unsigned char * blkgfxpt, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int i, j;

	destpt += (xoff*3)+(yoff*linesize);
	switch (blockdepth)
	{
	case 8:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = cmappt[(*blkgfxpt)*3+2];
		destpt[j*3+1] = cmappt[(*blkgfxpt)*3+1];
		destpt[j*3+2] = cmappt[(*blkgfxpt)*3];
		blkgfxpt++; }
		destpt += linesize; }
		break;
	case 15:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x3)<<3)|((*(blkgfxpt+1))>>5)))<<3;
		destpt[j*3+2] = (*blkgfxpt&0xFC)<<1;
		destpt[j*3] |= (destpt[j*3]>>5);
		destpt[j*3+1] |= (destpt[j*3+1]>>5);
		destpt[j*3+2] |= (destpt[j*3+2]>>5);
		blkgfxpt+=2; }
		destpt += linesize; }
		break;
	case 16:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x7)<<3)|((*(blkgfxpt+1))>>5)))<<2;
		destpt[j*3+2] = (*blkgfxpt&0xF8);
		destpt[j*3] |= (destpt[j*3]>>5);
		destpt[j*3+1] |= (destpt[j*3+1]>>6);
		destpt[j*3+2] |= (destpt[j*3+2]>>5);
		blkgfxpt+=2; }
		destpt += linesize; }
		break;
	case 24:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = blkgfxpt[2];
		destpt[j*3+1] = blkgfxpt[1];
		destpt[j*3+2] = blkgfxpt[0];
		blkgfxpt+=3; }
		destpt += linesize; }
		break;
	case 32:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = blkgfxpt[3];
		destpt[j*3+1] = blkgfxpt[2];
		destpt[j*3+2] = blkgfxpt[1];
		blkgfxpt+=4; }
		destpt += linesize; }
		break;
	}
}
*/

int IsBlockAttached (int blnum)
{
	if (blnum == 0 || isopillars == 0) return 0;
	if (blnum >= numblockstr) return 0;

	if (((BLKSTR *) blockstrpt)[blnum-1].unused1) return 1; else return 0;
}

void DrawBlock (unsigned char * blkgfxpt, unsigned char * destpt, int xoff, int yoff, int linesize, int flippart)
{
int i, j, istrt, iend, iadd, jstrt, jend, jadd;

	destpt += (xoff*3)+(yoff*linesize);

	if (!flippedtiles) {
	switch (blockdepth)
	{
	case 8:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j*3] = cmappt[(*blkgfxpt)*3+2];
		destpt[j*3+1] = cmappt[(*blkgfxpt)*3+1];
		destpt[j*3+2] = cmappt[(*blkgfxpt)*3];
		blkgfxpt++; }
		destpt += linesize; }
		break;
	case 15:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x3)<<3)|((*(blkgfxpt+1))>>5)))<<3;
		destpt[j*3+2] = (*blkgfxpt&0xFC)<<1;
		} else {
			destpt[j*3] = 0;
			destpt[j*3+1] = 0;
			destpt[j*3+2] = 0;
		}
		blkgfxpt+=2; }
		destpt += linesize; }
		break;
	case 16:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x7)<<3)|((*(blkgfxpt+1))>>5)))<<2;
		destpt[j*3+2] = (*blkgfxpt&0xF8);
		} else {
			destpt[j*3] = 0;
			destpt[j*3+1] = 0;
			destpt[j*3+2] = 0;
		}
		blkgfxpt+=2; }
		destpt += linesize; }
		break;
	case 24:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		if (!(*blkgfxpt==transred && *(blkgfxpt+1)==transgreen && *(blkgfxpt+2)==transblue)) {
		destpt[j*3] = blkgfxpt[2];
		destpt[j*3+1] = blkgfxpt[1];
		destpt[j*3+2] = blkgfxpt[0];
		} else {
			destpt[j*3] = 0;
			destpt[j*3+1] = 0;
			destpt[j*3+2] = 0;
		}
		blkgfxpt+=3; }
		destpt += linesize; }
		break;
	case 32:
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		if (!(*(blkgfxpt+1)==transred && *(blkgfxpt+2)==transgreen && *(blkgfxpt+3)==transblue)) {
		destpt[j*3] = blkgfxpt[3];
		destpt[j*3+1] = blkgfxpt[2];
		destpt[j*3+2] = blkgfxpt[1];
		} else {
			destpt[j*3] = 0;
			destpt[j*3+1] = 0;
			destpt[j*3+2] = 0;
		}
		blkgfxpt+=4; }
		destpt += linesize; }
		break;
	}
	return;
	}

//flipped tiles
	if (flippart&1) {
		jstrt = (blockwidth-1); jend = -1; jadd = -1;
	} else {
		jstrt = 0; jend = blockwidth; jadd = 1;
	}
	if (flippart&2) {
		istrt = (blockheight-1); iend = -1; iadd = -1;
	} else {
		istrt = 0; iend = blockheight; iadd = 1;
	}

	switch (blockdepth)
	{
	case 8:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		destpt[(i*linesize)+(j*3)] = cmappt[(*blkgfxpt)*3+2];
		destpt[(i*linesize)+(j*3+1)] = cmappt[(*blkgfxpt)*3+1];
		destpt[(i*linesize)+(j*3+2)] = cmappt[(*blkgfxpt)*3];
		blkgfxpt++; }
		}
		break;
	case 15:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[(i*linesize)+(j*3)] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[(i*linesize)+(j*3+1)] = (((((*blkgfxpt)&0x3)<<3)|((*(blkgfxpt+1))>>5)))<<3;
		destpt[(i*linesize)+(j*3+2)] = (*blkgfxpt&0xFC)<<1;
		} else {
			destpt[(i*linesize)+(j*3)] = 0;
			destpt[(i*linesize)+(j*3+1)] = 0;
			destpt[(i*linesize)+(j*3+2)] = 0;
		}
		blkgfxpt+=2; }
		}
		break;
	case 16:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[(i*linesize)+(j*3)] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[(i*linesize)+(j*3+1)] = (((((*blkgfxpt)&0x7)<<3)|((*(blkgfxpt+1))>>5)))<<2;
		destpt[(i*linesize)+(j*3+2)] = (*blkgfxpt&0xF8);
		} else {
			destpt[(i*linesize)+(j*3)] = 0;
			destpt[(i*linesize)+(j*3+1)] = 0;
			destpt[(i*linesize)+(j*3+2)] = 0;
		}
		blkgfxpt+=2; }
		}
		break;
	case 24:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*blkgfxpt==transred && *(blkgfxpt+1)==transgreen && *(blkgfxpt+2)==transblue)) {
		destpt[(i*linesize)+(j*3)] = blkgfxpt[2];
		destpt[(i*linesize)+(j*3+1)] = blkgfxpt[1];
		destpt[(i*linesize)+(j*3+2)] = blkgfxpt[0];
		} else {
			destpt[(i*linesize)+(j*3)] = 0;
			destpt[(i*linesize)+(j*3+1)] = 0;
			destpt[(i*linesize)+(j*3+2)] = 0;
		}
		blkgfxpt+=3; }
		}
		break;
	case 32:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt+1)==transred && *(blkgfxpt+2)==transgreen && *(blkgfxpt+3)==transblue)) {
		destpt[(i*linesize)+(j*3)] = blkgfxpt[3];
		destpt[(i*linesize)+(j*3+1)] = blkgfxpt[2];
		destpt[(i*linesize)+(j*3+2)] = blkgfxpt[1];
		} else {
			destpt[(i*linesize)+(j*3)] = 0;
			destpt[(i*linesize)+(j*3+1)] = 0;
			destpt[(i*linesize)+(j*3+2)] = 0;
		}
		blkgfxpt+=4; }
		}
		break;
	}
}

void OverBlock (unsigned char * blkgfxpt, unsigned char * destpt, int xoff, int yoff, int linesize, int isopart)
{
int i, j, istrt, iend, iadd, jstrt, jend, jadd;

	destpt += (xoff*3)+(yoff*linesize);
/*	switch (isopart) {
		case 1:
			stpos = 0; enpos = blockwidth/2;
			break;
		case 2:
			stpos = blockwidth/2; enpos = blockwidth;
			blkgfxpt += (stpos*((blockdepth+1)/8));
			break;
		default:
			stpos = 0; enpos = blockwidth;
			break;
	}
*/
	istrt = 0; iend = blockheight; iadd = 1;
	jstrt = 0; jend = blockwidth; jadd = 1;

	if (flippedtiles) {
//flipped tiles
		if (isopart&1) {
			jstrt = (blockwidth-1); jend = -1; jadd = -1;
		} else {
			jstrt = 0; jend = blockwidth; jadd = 1;
		}
		if (isopart&2) {
			istrt = (blockheight-1); iend = -1; iadd = -1;
		} else {
			istrt = 0; iend = blockheight; iadd = 1;
		}
	} else {
//isometric split pillars
		if (isopart == 3) isopart = 0;
		if (isopart&1) { jstrt = 0; jend = blockwidth/2; jadd = 1; }
		if (isopart&2) { jstrt = blockwidth/2; jend = blockwidth; jadd = 1; blkgfxpt += (jstrt*((blockdepth+1)/8)); }
	}

	switch (blockdepth)
	{
	case 8:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (*blkgfxpt!=trans8bit) {
		destpt[(i*linesize)+(j*3)] = cmappt[(*blkgfxpt)*3+2];
		destpt[(i*linesize)+(j*3+1)] = cmappt[(*blkgfxpt)*3+1];
		destpt[(i*linesize)+(j*3+2)] = cmappt[(*blkgfxpt)*3]; }
		blkgfxpt++; }
		if (isopart && !flippedtiles) blkgfxpt += blockwidth/2;
		}
		break;
	case 15:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[(i*linesize)+(j*3)] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[(i*linesize)+(j*3+1)] = (((((*blkgfxpt)&0x3)<<3)|((*(blkgfxpt+1))>>5)))<<3;
		destpt[(i*linesize)+(j*3+2)] = (*blkgfxpt&0xFC)<<1; }
		blkgfxpt+=2; }
		if (isopart && !flippedtiles) blkgfxpt += blockwidth;
		}
		break;
	case 16:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[(i*linesize)+(j*3)] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[(i*linesize)+(j*3+1)] = (((((*blkgfxpt)&0x7)<<3)|((*(blkgfxpt+1))>>5)))<<2;
		destpt[(i*linesize)+(j*3+2)] = (*blkgfxpt&0xF8); }
		blkgfxpt+=2; }
		if (isopart && !flippedtiles) blkgfxpt += blockwidth;
		}
		break;
	case 24:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*blkgfxpt==transred && *(blkgfxpt+1)==transgreen && *(blkgfxpt+2)==transblue)) {
		destpt[(i*linesize)+(j*3)] = blkgfxpt[2];
		destpt[(i*linesize)+(j*3+1)] = blkgfxpt[1];
		destpt[(i*linesize)+(j*3+2)] = blkgfxpt[0]; }
		blkgfxpt+=3; }
		if (isopart && !flippedtiles) blkgfxpt += (blockwidth)+(blockwidth/2);
		}
		break;
	case 32:
		for (i=istrt;i!=iend;i+=iadd) {	for (j=jstrt;j!=jend;j+=jadd) {
		if (!(*(blkgfxpt+1)==transred && *(blkgfxpt+2)==transgreen && *(blkgfxpt+3)==transblue)) {
		destpt[(i*linesize)+(j*3)] = blkgfxpt[3];
		destpt[(i*linesize)+(j*3+1)] = blkgfxpt[2];
		destpt[(i*linesize)+(j*3+2)] = blkgfxpt[1]; }
		blkgfxpt+=4; }
		if (isopart && !flippedtiles) blkgfxpt += blockwidth*2;
		}
		break;
	}
/*	switch (blockdepth)
	{
	case 8:
		for (i=0;i<blockheight;i++) {	for (j=stpos;j<enpos;j++) {
		if (*blkgfxpt!=trans8bit) {
		destpt[j*3] = cmappt[(*blkgfxpt)*3+2];
		destpt[j*3+1] = cmappt[(*blkgfxpt)*3+1];
		destpt[j*3+2] = cmappt[(*blkgfxpt)*3]; }
		blkgfxpt++; }
		if (isopart) blkgfxpt += blockwidth/2;
		destpt += linesize; }
		break;
	case 15:
		for (i=0;i<blockheight;i++) {	for (j=stpos;j<enpos;j++) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x3)<<3)|((*(blkgfxpt+1))>>5)))<<3;
		destpt[j*3+2] = (*blkgfxpt&0xFC)<<1; }
		blkgfxpt+=2; }
		if (isopart) blkgfxpt += blockwidth;
		destpt += linesize; }
		break;
	case 16:
		for (i=0;i<blockheight;i++) {	for (j=stpos;j<enpos;j++) {
		if (!(*(blkgfxpt)==trans16hi && *(blkgfxpt+1)==trans16low)) {
		destpt[j*3] = (*(blkgfxpt+1)&0x1F)<<3;
		destpt[j*3+1] = (((((*blkgfxpt)&0x7)<<3)|((*(blkgfxpt+1))>>5)))<<2;
		destpt[j*3+2] = (*blkgfxpt&0xF8); }
		blkgfxpt+=2; }
		if (isopart) blkgfxpt += blockwidth;
		destpt += linesize; }
		break;
	case 24:
		for (i=0;i<blockheight;i++) {	for (j=stpos;j<enpos;j++) {
		if (!(*blkgfxpt==transred && *(blkgfxpt+1)==transgreen && *(blkgfxpt+2)==transblue)) {
		destpt[j*3] = blkgfxpt[2];
		destpt[j*3+1] = blkgfxpt[1];
		destpt[j*3+2] = blkgfxpt[0]; }
		blkgfxpt+=3; }
		if (isopart) blkgfxpt += (blockwidth+(blockwidth/2));
		destpt += linesize; }
		break;
	case 32:
		for (i=0;i<blockheight;i++) {	for (j=stpos;j<enpos;j++) {
		if (!(*(blkgfxpt+1)==transred && *(blkgfxpt+2)==transgreen && *(blkgfxpt+3)==transblue)) {
		destpt[j*3] = blkgfxpt[3];
		destpt[j*3+1] = blkgfxpt[2];
		destpt[j*3+2] = blkgfxpt[1]; }
		blkgfxpt+=4; }
		if (isopart) blkgfxpt += blockwidth*2;
		destpt += linesize; }
		break;
	}
*/
}

void Onionto24 (int x, int y, unsigned char * destpt, int xoff, int yoff, int linesize, int olayer)
{
int i, isop;
long int * templpt;
short int * mymappt;
unsigned char * srcpt;
BLKSTR * blkdatapt;
ANISTR * myanpt;

	srcpt = (unsigned char *) blockgfxpt;
	if (x<mapwidth && y<mapheight && x>=0 && y>=0)
	{
		if (olayer<0) mymappt = mappt;
		else mymappt = mapmappt[olayer];
		if (mymappt == NULL) return;
		mymappt += x+(y*mapwidth);

		if (*mymappt>=0) blkdatapt = (BLKSTR*) (((char *)blockstrpt) + (((int)(*mymappt))*sizeof(BLKSTR)));
		else { myanpt = (ANISTR *) ((animstrpt+ANDTMEM)+(*mymappt));
			templpt = (long int *) ((animstrpt+ANDTMEM)+(myanpt->anstartoff)); templpt--;
			blkdatapt = (BLKSTR *) (blockstrpt + (*templpt)); }

		if (blockstaggerx || blockstaggery) {
		if (blkdatapt->bgoff) {
			OverBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, 0);
		}
		isop = 0;
		if (isopillars && blkdatapt->unused2 && !blkdatapt->unused3) isop = 1;
		if (isopillars && !blkdatapt->unused2 && blkdatapt->unused3) isop = 2;
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) yoff -= blockheight;
		if (yoff < 0 || isoreveal) return;
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) yoff -= blockheight;
		if (yoff < 0) return;
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
		}
		while (blkdatapt->unused1) {
			blkdatapt++;
			isop = 0;
			if (isopillars && blkdatapt->unused2 && !blkdatapt->unused3) isop = 1;
			if (isopillars && !blkdatapt->unused2 && blkdatapt->unused3) isop = 2;
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->bgoff) {
				OverBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff) {
				OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff2) {
				OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff3) {
				OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
			}
		}
		} else {
		DrawBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, 0);
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, 0);
		}
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, 0);
		}
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, 0);
		}
		}
	} else {
		destpt += (xoff*3)+(yoff*linesize);
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0x44, blockwidth*3);
			destpt += linesize;
		}
	}
}

void Overlayto24 (int x, int y, unsigned char * destpt, int xoff, int yoff, int linesize, int olayer)
{
int i, isop;
long int * templpt;
short int * mymappt;
unsigned char * srcpt;
BLKSTR * blkdatapt;
ANISTR * myanpt;

	srcpt = (unsigned char *) blockgfxpt;
	if (x<mapwidth && y<mapheight && x>=0 && y>=0)
	{
		if (olayer<0) mymappt = mappt;
		else mymappt = mapmappt[olayer];
		if (mymappt == NULL) return;
		mymappt += x+(y*mapwidth);

		if (*mymappt>=0) blkdatapt = (BLKSTR*) (((char *)blockstrpt) + (((int)(*mymappt))*sizeof(BLKSTR)));
		else { myanpt = (ANISTR *) ((animstrpt+ANDTMEM)+(*mymappt));
			templpt = (long int *) ((animstrpt+ANDTMEM)+(myanpt->anstartoff)); templpt--;
			blkdatapt = (BLKSTR *) (blockstrpt + (*templpt)); }

		if (blkdatapt->bgoff) {
			OverBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, 0);
		}
		isop = 0;
		if (isopillars && blkdatapt->unused2 && !blkdatapt->unused3) isop = 1;
		if (isopillars && !blkdatapt->unused2 && blkdatapt->unused3) isop = 2;
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) yoff -= blockheight;
		if (yoff < 0 || isoreveal) return;
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) yoff -= blockheight;
		if (yoff < 0) return;
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
		}
		while (blkdatapt->unused1) {
			blkdatapt++;
			isop = 0;
			if (isopillars && blkdatapt->unused2 && !blkdatapt->unused3) isop = 1;
			if (isopillars && !blkdatapt->unused2 && blkdatapt->unused3) isop = 2;
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->bgoff) {
				OverBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff) {
				OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff2) {
				OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
			}
			if (isopillars) yoff -= blockheight;
			if (yoff < 0) return;
			if (blkdatapt->fgoff3) {
				OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
			}
		}
	} else {
		destpt += (xoff*3)+(yoff*linesize);
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0x44, blockwidth*3);
			destpt += linesize;
		}
	}
}

void Blockto24 (int x, int y, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int i, isop;
long int * templpt;
short int * mymappt;
unsigned char * srcpt;
BLKSTR * blkdatapt;
ANISTR * myanpt;

	srcpt = (unsigned char *) blockgfxpt;
	if (x<mapwidth && y<mapheight && x>=0 && y>=0)
	{
		mymappt = mappt;
		mymappt += x+(y*mapwidth);

		if (*mymappt>=0) blkdatapt = (BLKSTR*) (((char *)blockstrpt) + (((int)(*mymappt))*sizeof(BLKSTR)));
		else { myanpt = (ANISTR *) ((animstrpt+ANDTMEM)+(*mymappt));
			templpt = (long int *) ((animstrpt+ANDTMEM)+(myanpt->anstartoff)); templpt--;
			blkdatapt = (BLKSTR *) (blockstrpt + (*templpt)); }

		isop = 0;
		if (isopillars && blkdatapt->unused2 && !blkdatapt->unused3) isop = 1;
		if (isopillars && !blkdatapt->unused2 && blkdatapt->unused3) isop = 2;
		if (flippedtiles && blkdatapt->unused2) isop = 1;
		if (flippedtiles && blkdatapt->unused3) isop += 2;
		DrawBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) return;
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
		}
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
		}
	} else {
		destpt += (xoff*3)+(yoff*linesize);
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0x44, blockwidth*3);
			destpt += linesize;
		}
	}
}

void BlockSecto24 (int strnum, unsigned char * destpt, int xoff, int yoff, int linesize, int bpart)
{
int isop;
unsigned char * srcpt;
BLKSTR * blkdatapt;

	srcpt = (unsigned char *) blockgfxpt;
	if (strnum<numblockstr && strnum>-1)
	{
		blkdatapt = (BLKSTR*) (((char *)blockstrpt) + (strnum*(sizeof(BLKSTR))));

		isop = 0;
		if (flippedtiles && blkdatapt->unused2) isop = 1;
		if (flippedtiles && blkdatapt->unused3) isop += 2;
		switch (bpart) {
			case 0:
				DrawBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
				break;
			case 1:
				DrawBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
				break;
			case 2:
				DrawBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
				break;
			case 3:
				DrawBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
				break;
		}
	}
}

void BlockGfxto24 (int gfxnum, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int i;
unsigned char * srcpt;

	srcpt = (unsigned char *) blockgfxpt;
	if (gfxnum<numblockgfx && gfxnum>-1)
	{
		DrawBlock (srcpt+(gfxnum*blockwidth*blockheight*((blockdepth+1)/8)), destpt, xoff, yoff, linesize, 0);
	} else {
		destpt += (xoff*3)+(yoff*linesize);
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0x44, blockwidth*3);
			destpt += linesize;
		}
	}
}

void BlockGfxto8 (int gfxnum, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int i, j;
unsigned char * srcpt;

	srcpt = (unsigned char *) blockgfxpt;
	srcpt += gfxnum*blockwidth*blockheight;
	destpt += xoff+(yoff*linesize);
	if (gfxnum<numblockgfx && gfxnum>-1 && blockdepth==8)
	{
		for (i=0;i<blockheight;i++) {	for (j=0;j<blockwidth;j++) {
		destpt[j] = srcpt[0];
		srcpt++; }
		destpt += linesize; }
	} else {
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0, blockwidth);
			destpt += linesize;
		}
	}
}

void BlockStrto24 (int strnum, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int i, isop;
unsigned char * srcpt;
BLKSTR * blkdatapt;

	srcpt = (unsigned char *) blockgfxpt;
	if (strnum<numblockstr && strnum>-1)
	{
		blkdatapt = (BLKSTR*) (((char *)blockstrpt) + (((int)strnum)*(sizeof(BLKSTR))));

		isop = 0;
		if (flippedtiles && blkdatapt->unused2) isop = 1;
		if (flippedtiles && blkdatapt->unused3) isop += 2;
		DrawBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) return;
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
		}
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
		}
	} else {
		destpt += (xoff*3)+(yoff*linesize);
		for (i=0;i<blockheight;i++) {
			memset (destpt, 0x44, blockwidth*3);
			destpt += linesize;
		}
	}
}

void BlockAnimto24 (int aninum, int frame, unsigned char * destpt, int xoff, int yoff, int linesize)
{
int isop;
unsigned char * srcpt;
long int * templpt;
ANISTR * myanimpt;
BLKSTR * blkdatapt;

	if (animstrpt==NULL) return;
	srcpt = (unsigned char *) blockgfxpt;
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM);
	myanimpt--;
	if (myanimpt->antype==AN_END) return;
	while (aninum) {
		myanimpt--; aninum--;
		if (myanimpt->antype==AN_END) return;
	}

		templpt = (long int *) ((animstrpt+ANDTMEM)+(myanimpt->anstartoff));
		if (frame==-1) templpt--;
		else templpt += frame;
		blkdatapt = (BLKSTR *) (blockstrpt + (*templpt));

		isop = 0;
		if (flippedtiles && blkdatapt->unused2) isop = 1;
		if (flippedtiles && blkdatapt->unused3) isop += 2;
		DrawBlock (srcpt+(blkdatapt->bgoff), destpt, xoff, yoff, linesize, isop);
		if (blkdatapt->fgoff) {
			OverBlock (srcpt+(blkdatapt->fgoff), destpt, xoff, yoff, linesize, isop);
		}
		if (isopillars) return;
		if (blkdatapt->fgoff2) {
			OverBlock (srcpt+(blkdatapt->fgoff2), destpt, xoff, yoff, linesize, isop);
		}
		if (blkdatapt->fgoff3) {
			OverBlock (srcpt+(blkdatapt->fgoff3), destpt, xoff, yoff, linesize, isop);
		}
}

void PlaceTile (int xoff, int yoff)
{
int k, l, m;
short int * mymappt = mappt;
short int * mymap2pt;
short int * mybrshpt;

	if (mappt==NULL) return;
	if (xoff<0 || xoff>=mapwidth) return;
	if (yoff<0 || yoff>=mapheight) return;

	if (curbrsh>0 && curbrsh<=MAXBRSH) {
		if ((blockstaggerx || blockstaggery) && (yoff&1)) yoff--;
	}
	if ((xoff+(yoff*mapwidth))==curplacetile) return;
	curplacetile = (xoff+(yoff*mapwidth));
	mymappt += (xoff+(yoff*mapwidth));

	if (!(curbrsh>0 && curbrsh<=MAXBRSH)) { if (curanim>=0)
	{
		*mymappt = -((curanim+1)*sizeof(ANISTR));
		return;
	} }

	if (curbrsh>0 && curbrsh<=MAXBRSH)
	{
		if (brshpt[curbrsh-1]==NULL) return;
		mybrshpt = brshpt[curbrsh-1];
		k = (int) *mybrshpt; mybrshpt++; l = (int) *mybrshpt; mybrshpt++;
		if ((xoff+k)<0 || (xoff+k)>mapwidth) return;
		if ((yoff+l)<0 || (yoff+l)>mapheight) return;
		while (l) {
			mymap2pt = mymappt;
			m = k; while (k) {
				logit ("X=%d, Y=%d, val=%d\n", k, l, *mybrshpt);
				if (*mybrshpt || pastebrushnt) *mymappt = *mybrshpt;
				mymappt++; mybrshpt++; k--;
			}
			mymappt = mymap2pt; mymappt += mapwidth;
			l--; k = m;
		}
	} else { if (curanim==-1) { *mymappt = curstr;
	} }
}

int MakeBrush (int x1, int y1, int x2, int y2)
{
int k, l;
short int * mybrshpt, * mymappt, * mymap2pt;

	if (curbrsh<1 || curbrsh>MAXBRSH) return -1;
	if (x1<0 || x2<0 || y1<0 || y2<0) return -1;
	if (x1>=mapwidth || x2>=mapwidth || y1>=mapheight || y2>=mapheight) return -1;
	if (brshpt[curbrsh-1]!=NULL) free (brshpt[curbrsh-1]); brshpt[curbrsh-1] = NULL;

	brshpt[curbrsh-1] = malloc ((((x2-x1)+1)*((y2-y1)+1)*2)+4);
	if (brshpt[curbrsh-1]==NULL) return -1;

	mybrshpt = (short int *) brshpt[curbrsh-1];
	*mybrshpt = (x2-x1)+1; mybrshpt++;
	*mybrshpt = (y2-y1)+1; mybrshpt++;
	mymappt = (short int *) mapmappt[maplayer];
	mymappt += (y1*((int)mapwidth));
	mymappt += x1;
	for (k=0;k<(y2-y1+1);k++)
	{
		mymap2pt = mymappt;
		for (l=0;l<(x2-x1+1);l++)
		{
			*mybrshpt = *mymappt;
			mybrshpt++; mymappt++;
		}
		mymappt = mymap2pt;
		mymappt += mapwidth;
	}
	return 0;
}

int MakeBrushBS (int bsstart, int bswidth, int bsheight, int bsmodu)
{
int j, k;
short int * mybrshpt;
BLKSTR * myblkstrpt;

	if (curbrsh<1 || curbrsh>MAXBRSH) return -1;
	if (brshpt[curbrsh-1]!=NULL) free (brshpt[curbrsh-1]); brshpt[curbrsh-1] = NULL;

	brshpt[curbrsh-1] = malloc ((bswidth*bsheight*2)+4);
	if (brshpt[curbrsh-1]==NULL) return -1;

	mybrshpt = (short int *) brshpt[curbrsh-1];
	*mybrshpt = bswidth; mybrshpt++;
	*mybrshpt = bsheight; mybrshpt++;

	myblkstrpt = (BLKSTR *) blockstrpt;

	for (j=0;j<bsheight;j++)
	{
		for (k=0;k<bswidth;k++)
		{
			if (bsstart >= numblockstr || bsstart < 0) {
				free (brshpt[curbrsh-1]); brshpt[curbrsh-1] = NULL;
				return -1;
			}
			*mybrshpt = bsstart;
			mybrshpt++; bsstart++;
		}
		bsstart += bsmodu;
	}
	return 0;
}

void DestroyAllBrushes (void)
{
int i;

	for (i=0;i<MAXBRSH;i++) {
		if (brshpt[i]!=NULL) { free (brshpt[i]); brshpt[i] = NULL; }
		strcpy (brshname[i], "Brush");
	}
}

void NewBlock (void)
{
int i, j, k;
short int * mymappt;
char * strpt = (char *) blockstrpt;
ANISTR * myanpt;
long int * templpt;

	curstr++; numblockstr++; strpt+=(((int)curstr)*BLOCKSTRSIZE);
	InsertBytes (strpt, blockstrpt+BKDTMEM, BLOCKSTRSIZE);

	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	for (j=0;j<mapheight;j++)
	{
		for (i=0;i<mapwidth;i++)
		{
			if (*mymappt>=(curstr)) (*mymappt)++; mymappt++;
		}
	} } }
	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
		if (*mymappt>=(curstr)) (*mymappt)++;
		mymappt++; i--; } } }

	if (animstrpt != NULL) {
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=-1) myanpt--;
	templpt = (long int *) animstrpt;
	while (templpt!=(long int *) myanpt)
	{ if (*templpt>=(((int)curstr)*BLOCKSTRSIZE)) *templpt+=BLOCKSTRSIZE; templpt++; }
	}
}

void CutBlock (void)
{
short int i, j, k;
short int * mymappt;
char * blktpt = blockstrpt;
BLKSTR * blkpt;
ANISTR * myanpt;
long int * templpt;

	if (!curstr) return;
	blktpt += ((int)curstr)*BLOCKSTRSIZE;
	blkpt = (BLKSTR *) blktpt;
	blkbuffer.bgoff = blkpt->bgoff;
	blkbuffer.fgoff = blkpt->fgoff;
	blkbuffer.fgoff2 = blkpt->fgoff2;
	blkbuffer.fgoff3 = blkpt->fgoff3;
	blkbuffer.user1 = blkpt->user1;
	blkbuffer.user2 = blkpt->user2;
	blkbuffer.user3 = blkpt->user3;
	blkbuffer.user4 = blkpt->user4;
	blkbuffer.user5 = blkpt->user5;
	blkbuffer.user6 = blkpt->user6;
	blkbuffer.user7 = blkpt->user7;
	blkbuffer.tl = blkpt->tl;
	blkbuffer.tr = blkpt->tr;
	blkbuffer.bl = blkpt->bl;
	blkbuffer.br = blkpt->br;
	blkbuffer.trigger = blkpt->trigger;
	blkbuffer.unused1 = blkpt->unused1;
	blkbuffer.unused2 = blkpt->unused2;
	blkbuffer.unused3 = blkpt->unused3;
	RemoveBytes (blktpt, blockstrpt+BKDTMEM, BLOCKSTRSIZE);
	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	for (j=0;j<mapheight;j++)
	{
		for (i=0;i<mapwidth;i++)
		{
			if (*mymappt>curstr) (*mymappt)--;
			else if (*mymappt==curstr) (*mymappt)=0;
			mymappt++;
		}
	} } }
	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
			if (*mymappt>curstr) (*mymappt)--;
			else if (*mymappt==curstr) (*mymappt)=0;
		mymappt++; i--; } } }

	if (animstrpt != NULL) {
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=-1) myanpt--;
	templpt = (long int *) animstrpt;
	while (templpt!=(long int *) myanpt)
	{ if (*templpt>(((int)curstr)*BLOCKSTRSIZE)) *templpt-=BLOCKSTRSIZE;
		else if (*templpt==(((int)curstr)*BLOCKSTRSIZE)) *templpt = 0; templpt++; }
	}

	numblockstr--; if (curstr==numblockstr) curstr--;
}

void CopyBlock (void)
{
char * blktpt = blockstrpt;
BLKSTR * blkpt;

	blktpt += ((int)curstr)*BLOCKSTRSIZE;
	blkpt = (BLKSTR *) blktpt;
	blkbuffer.bgoff = blkpt->bgoff;
	blkbuffer.fgoff = blkpt->fgoff;
	blkbuffer.fgoff2 = blkpt->fgoff2;
	blkbuffer.fgoff3 = blkpt->fgoff3;
	blkbuffer.user1 = blkpt->user1;
	blkbuffer.user2 = blkpt->user2;
	blkbuffer.user3 = blkpt->user3;
	blkbuffer.user4 = blkpt->user4;
	blkbuffer.user5 = blkpt->user5;
	blkbuffer.user6 = blkpt->user6;
	blkbuffer.user7 = blkpt->user7;
	blkbuffer.tl = blkpt->tl;
	blkbuffer.tr = blkpt->tr;
	blkbuffer.bl = blkpt->bl;
	blkbuffer.br = blkpt->br;
	blkbuffer.trigger = blkpt->trigger;
	blkbuffer.unused1 = blkpt->unused1;
	blkbuffer.unused2 = blkpt->unused2;
	blkbuffer.unused3 = blkpt->unused3;
}

void PasteBlock (void)
{
short int i, j, k;
short int * mymappt;
char * blktpt = blockstrpt;
BLKSTR * blkpt;
ANISTR * myanpt;
long int * templpt;

	curstr++; numblockstr++;
	blktpt += ((int)curstr)*BLOCKSTRSIZE;
	InsertBytes (blktpt, blockstrpt+BKDTMEM, BLOCKSTRSIZE);
	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	for (j=0;j<mapheight;j++)
	{
		for (i=0;i<mapwidth;i++)
		{
			if (*mymappt>=(curstr)) (*mymappt)++; mymappt++;
		}
	} } }
	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
		if (*mymappt>=(curstr)) (*mymappt)++;
		mymappt++; i--; } } }

	if (animstrpt != NULL) {
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=-1) myanpt--;
	templpt = (long int *) animstrpt;
	while (templpt!=(long int *) myanpt)
	{ if (*templpt>=(curstr*BLOCKSTRSIZE)) *templpt+=BLOCKSTRSIZE; templpt++; }
	}

	blkpt = (BLKSTR *) blktpt;
	blkpt->bgoff = blkbuffer.bgoff;
	blkpt->fgoff = blkbuffer.fgoff;
	blkpt->fgoff2 = blkbuffer.fgoff2;
	blkpt->fgoff3 = blkbuffer.fgoff3;
	blkpt->user1 = blkbuffer.user1;
	blkpt->user2 = blkbuffer.user2;
	blkpt->user3 = blkbuffer.user3;
	blkpt->user4 = blkbuffer.user4;
	blkpt->user5 = blkbuffer.user5;
	blkpt->user6 = blkbuffer.user6;
	blkpt->user7 = blkbuffer.user7;
	blkpt->tl = blkbuffer.tl;
	blkpt->tr = blkbuffer.tr;
	blkpt->bl = blkbuffer.bl;
	blkpt->br = blkbuffer.br;
	blkpt->trigger = blkbuffer.trigger;
	blkpt->unused1 = blkbuffer.unused1;
	blkpt->unused2 = blkbuffer.unused2;
	blkpt->unused3 = blkbuffer.unused3;
}

void DestroyUnusedBlocks (void)
{
int blkcount, blkfound, i, j, k;
short int curblocktemp;
ANISTR *myanpt;
long int * templpt;
short int * mymappt;

	if (mappt==NULL) return;
	if (blockstrpt==NULL) return;

	blkcount = (numblockstr-1); while (blkcount) {
	blkfound = 0;
   if (isopillars && blkcount > 0) { if (((BLKSTR *) blockstrpt)[blkcount-1].unused1) blkfound = 1; }
	for (k=0;k<8;k++) {
		mymappt = mapmappt[k]; if (mymappt!=NULL) {
		for (j=0;j<mapheight;j++) {
			for (i=0;i<mapwidth;i++) {
				if (*mymappt == (blkcount)) { blkfound = 1; break; }
				mymappt++;
			}
			if (blkfound) break;
		}
		if (blkfound) break;
	} }
	if (animstrpt != NULL && !blkfound) {
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	while (myanpt->antype!=-1) myanpt--;
	templpt = (long int *) animstrpt;
	while (templpt!=(long int *) myanpt)
	{
		if (*templpt==(blkcount*sizeof(BLKSTR))) { blkfound = 1; break; }
		templpt++;
	} }
	blkcount--;
	if (!blkfound) {
		curblocktemp = curstr; curstr = blkcount+1;
		CutBlock (); curstr = curblocktemp; }
	}
	curanim = -1; curstr = 0;
}

void CorrectBlockStructures (void)
{
int i, j;
BLKSTR * myblk;

	myblk = (BLKSTR *) blockstrpt;
	j = blockwidth*blockheight*((blockdepth+1)/8)*numblockgfx;
	for (i=0;i<numblockstr;i++) {
		if (myblk->bgoff >= j) myblk->bgoff = 0;
		if (myblk->fgoff >= j) myblk->fgoff = 0;
		if (myblk->fgoff2 >= j) myblk->fgoff2 = 0;
		if (myblk->fgoff3 >= j) myblk->fgoff3 = 0;
      myblk++;
	}
}

void AnimNew (void)
{
int i, j, k;
ANISTR * myanimpt;
ANISTR * myanim3pt;
char * myanim2pt;
long int * templpt;
short int * mymappt;

	if (animstrpt==NULL)
	{
		animstrpt = malloc (ANDTMEM);
		if (animstrpt == NULL) return;
		memset (animstrpt, 0, ANDTMEM);
		*(animstrpt+ANDTMEM-sizeof(ANISTR))=-1;
		if (curanim==-1) curanim = 0;
		numblockanim = 1;
	} else {
		if (numblockanim) curanim++;
		numblockanim++;
	}
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM);
	myanimpt -= curanim; j = -((curanim+1)*sizeof(ANISTR));
	InsertBytesR ((char *) animstrpt, (char *) myanimpt, sizeof(ANISTR));
	myanimpt--; myanimpt->antype = AN_NONE; myanimpt->andelay = 3;
	myanimpt->ancount = myanimpt->andelay; myanimpt->anuser = 0;
	myanim2pt = (char *) (animstrpt+ANDTMEM);
	myanim2pt -= (sizeof(ANISTR)*(numblockanim+1));
	InsertBytesR ((char *) animstrpt, (char *) myanim2pt, 4);
	myanim3pt = (ANISTR *) (animstrpt+ANDTMEM); myanim3pt--;
	while (myanim3pt->antype!=-1)
	{
		if ((myanim3pt->anstartoff)<=((myanim2pt-(animstrpt+ANDTMEM))+sizeof(ANISTR)))
		{
			myanim3pt->anstartoff -= (4+sizeof(ANISTR));
			myanim3pt->ancuroff -= (4+sizeof(ANISTR));
			myanim3pt->anendoff -= (4+sizeof(ANISTR));
		}
		myanim3pt--;
	}
	myanimpt->anstartoff = (myanim2pt-(animstrpt+ANDTMEM));
	myanimpt->ancuroff = (myanim2pt-(animstrpt+ANDTMEM));
	myanimpt->anendoff = (myanim2pt-(animstrpt+ANDTMEM));
	myanim2pt -= 4; templpt = (long int *) myanim2pt; *templpt=0;
	/* (int) curstr*sizeof(BLKSTR); */

	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	i = mapwidth*mapheight; while (i) {
		if (*mymappt<=j) *mymappt -= sizeof(ANISTR);
		mymappt++; i--; } } }

	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
		if (*mymappt<=j) *mymappt -= sizeof(ANISTR);
		mymappt++; i--; } } }
}

void AnimCut (void)
{
int i, k, copycount;
ANISTR * myanimpt;
char * myanim2pt;
char * myabpt;
char * mycpypt;
long int * myab2pt;
short int * mymappt;

	if (!numblockanim) return;
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM);
	myanimpt -= curanim; myanimpt--;
	if (animbufferpt==NULL) animbufferpt = malloc (ABUFMEM);
	myabpt = animbufferpt;
	*myabpt = myanimpt->antype; myabpt++;
	*myabpt = myanimpt->andelay; myabpt++;
	*myabpt = myanimpt->ancount; myabpt++;
	*myabpt = myanimpt->anuser; myabpt++;
	myab2pt = (long int *) myabpt;
	*myab2pt = ((myanimpt->anendoff)-(myanimpt->anstartoff))+4;
	myabpt += 4; copycount = *myab2pt; mycpypt = (char *) (animstrpt+ANDTMEM);
	mycpypt += myanimpt->anstartoff; myanim2pt = (char *) mycpypt; mycpypt -= 4;
	while (copycount) { *myabpt = *mycpypt; myabpt++; mycpypt++; copycount--; }

	myanimpt++; RemoveBytesR ( (char *) animstrpt, (char *) myanimpt, sizeof(ANISTR));
	RemoveBytesR ( (char *) animstrpt, (char *) ((myanim2pt+sizeof(ANISTR))+(*myab2pt)-4),
		*myab2pt);
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM); myanimpt--;
	while (myanimpt->antype!=-1)
	{
		if ((myanimpt->anstartoff)<=((int) (myanim2pt-(animstrpt+ANDTMEM))))
		{
			myanimpt->anstartoff += *myab2pt;
			myanimpt->ancuroff += *myab2pt;
			myanimpt->anendoff += *myab2pt;
		}
		myanimpt->anstartoff += (sizeof(ANISTR));
		myanimpt->ancuroff += (sizeof(ANISTR));
		myanimpt->anendoff += (sizeof(ANISTR));
		myanimpt--;
	}
	copycount = -((curanim+1)*sizeof(ANISTR));
	numblockanim--; if (numblockanim==curanim) curanim--; if (curanim<0) curanim = 0;

	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	i = mapwidth*mapheight; while (i) {
		if (*mymappt<copycount) *mymappt += sizeof(ANISTR);
		else if (*mymappt==copycount) *mymappt = 0;
		mymappt++; i--; } } }

	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
		if (*mymappt<copycount) *mymappt += sizeof(ANISTR);
		else if (*mymappt==copycount) *mymappt = 0;
		mymappt++; i--; } } }

	if (numblockanim==0) { free (animstrpt); animstrpt = NULL; curanim = -1; }
}

void AnimCopy (void)
{
int copycount;
ANISTR * myanimpt;
char * myabpt;
char * mycpypt;
long int * myab2pt;
	if (!numblockanim) return;
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM);
	myanimpt -= curanim; myanimpt--;
	if (animbufferpt==NULL) animbufferpt = malloc (ABUFMEM);
	myabpt = animbufferpt;
	*myabpt = myanimpt->antype; myabpt++;
	*myabpt = myanimpt->andelay; myabpt++;
	*myabpt = myanimpt->ancount; myabpt++;
	*myabpt = myanimpt->anuser; myabpt++;
	myab2pt = (long int *) myabpt;
	*myab2pt = (myanimpt->anendoff-myanimpt->anstartoff)+4;
	myabpt += 4; copycount = *myab2pt; mycpypt = (char *) (animstrpt+ANDTMEM);
	mycpypt += myanimpt->anstartoff; mycpypt -= 4;
	while (copycount) { *myabpt = *mycpypt; myabpt++; mycpypt++; copycount--; }
}

void AnimPaste (void)
{
int i, j, k, copycount;
ANISTR * myanimpt;
ANISTR * myanim2pt;
char * myabpt;
char * mycpypt;
long int * myab2pt;
short int * mymappt;

	if (animbufferpt==NULL) return;
	myanimpt = (ANISTR *) (animstrpt+ANDTMEM); myanimpt--;
	myab2pt = (long int *) animbufferpt; myab2pt++; copycount = *myab2pt;
	while (myanimpt->antype!=-1) { myanimpt->anstartoff -= (sizeof(ANISTR)+copycount);
	myanimpt->ancuroff -= (sizeof(ANISTR)+ copycount);
	myanimpt->anendoff -= (sizeof(ANISTR)+ copycount); myanimpt--; }

	myanimpt = (ANISTR *) (animstrpt+ANDTMEM);
	myanimpt -= curanim; /* if (numblockanim!=0) myanimpt--; */
	j = -((curanim+1)*sizeof(ANISTR));
	InsertBytesR ((char *) animstrpt, (char *) myanimpt, sizeof(ANISTR));
	myabpt = animbufferpt; myanimpt--;
	myanimpt->antype = *myabpt; myabpt++;
	myanimpt->andelay = *myabpt; myabpt++;
	myanimpt->ancount = *myabpt; myabpt++;
	myanimpt->anuser = *myabpt; myabpt++; myabpt += 4;
	myanim2pt = (ANISTR *) myanimpt;
	while (myanim2pt->antype!=-1) myanim2pt--;
	InsertBytesR ((char *) animstrpt, (char *) myanim2pt, copycount);
	mycpypt = (char *) myanim2pt; mycpypt -= copycount; copycount -=4;
	*mycpypt = *myabpt; mycpypt++; myabpt++; *mycpypt = *myabpt; mycpypt++; myabpt++;
	*mycpypt = *myabpt; mycpypt++; myabpt++; *mycpypt = *myabpt; mycpypt++; myabpt++;
	myanimpt->anstartoff = (mycpypt-(animstrpt+ANDTMEM));
	myanimpt->ancuroff = (mycpypt-(animstrpt+ANDTMEM));
	while (copycount) { *mycpypt = *myabpt; mycpypt++; myabpt++; copycount--; }
	myanimpt->anendoff = (mycpypt-(animstrpt+ANDTMEM));

	for (k=0;k<8;k++) { mymappt = mapmappt[k]; if (mymappt != NULL) {
	i = mapwidth*mapheight; while (i) {
		if (*mymappt<=j) *mymappt -= sizeof(ANISTR);
		mymappt++; i--; } } }

	for (k=0;k<MAXBRSH;k++) {
	if (brshpt[k]) { mymappt = brshpt[k]; i = *mymappt; mymappt++; i *= *mymappt; mymappt++;
	while (i) {
		if (*mymappt<=j) *mymappt -= sizeof(ANISTR);
		mymappt++; i--; } } }

	numblockanim++; curanim++;
}

void PickBlock (int x, int y)
{
short int * mymappt;

	if (x<0 || x>=mapwidth || y<0 || y>=mapheight) return;
	if (mappt==NULL) return;
	curbrsh = 0;
	mymappt = mappt;
	mymappt += x+(y*((int)mapwidth));
	if (mymappt[0]<0) curanim = ((-(*mymappt))/(sizeof(ANISTR)))-1;
	else { curanim = -1; curstr = (*mymappt); }
}

void DelAnimFrame (int anum, int epoint)
{
long int insertoff, tempoff;
ANISTR * myanpt;
ANISTR * myan2pt;
long int * templpt;

	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
	insertoff = myanpt->anstartoff; insertoff += epoint*sizeof(long int);
	if (insertoff>=(myanpt->anendoff)) return;
	templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff); templpt++;
	RemoveBytesR ((char *) animstrpt, (char *) templpt, 4);

	myan2pt = (ANISTR *) myanpt; tempoff = myanpt->anstartoff;
	myanpt = (ANISTR *) (animstrpt+ANDTMEM);
	while (myanpt->antype!=-1)
	{
		if ((myanpt->anstartoff) < insertoff) myanpt->anstartoff += 4;
		if ((myanpt->ancuroff) < insertoff) myanpt->ancuroff += 4;
		if ((myanpt->anendoff) < insertoff) myanpt->anendoff += 4;
		myanpt--;
	}
	myan2pt->anstartoff = tempoff+4;
}

void DestroyUnusedAnims (void)
{
int ancount, anfound, i, j, k;
short int curanimtemp;
ANISTR * myanpt;
short int * mymappt;

	if (mappt==NULL) return;
	if (animstrpt==NULL) return;
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt--;
	ancount = 0; while (myanpt->antype!=-1) { ancount++; myanpt--; }

	while (ancount) {
	anfound = 0;
	for (k=0;k<8;k++) {
		mymappt = mapmappt[k]; if (mymappt!=NULL) {
		for (j=0;j<mapheight;j++) {
			for (i=0;i<mapwidth;i++) {
				if (*mymappt == -((ancount)*sizeof(ANISTR))) { anfound = 1; break; }
				mymappt++;
			}
			if (anfound) break;
		}
		if (anfound) break;
	} }
	ancount--;
	if (!anfound) { curanimtemp = curanim; curanim = ancount;
		AnimCut (); curanim = curanimtemp; }
	}
	curanim = -1; curstr = 0;
}

void InsertAnimFrame (int anum, int epoint, int frame)
{
long int insertoff, tempoff;
ANISTR * myanpt;
ANISTR * myan2pt;
long int * templpt;

	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
	insertoff = myanpt->anstartoff; insertoff += epoint*sizeof(long int);
	if (insertoff>(myanpt->anendoff)) return;
	templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);
	InsertBytesR ((char *) animstrpt, (char *) templpt, 4);
	templpt--; *templpt = frame*BLOCKSTRSIZE;

	myan2pt = (ANISTR *) myanpt; tempoff = myanpt->anstartoff;
	myanpt = (ANISTR *) (animstrpt+ANDTMEM);
	while (myanpt->antype!=-1)
	{
		if ((myanpt->anstartoff) < insertoff) myanpt->anstartoff -= 4;
		if ((myanpt->ancuroff) < insertoff) myanpt->ancuroff -= 4;
		if ((myanpt->anendoff) < insertoff) myanpt->anendoff -= 4;
		myanpt--;
	}
	myan2pt->anstartoff = tempoff-4;
}

void SetRefFrame (int refsnum, int frame)
{
long int insertoff;
ANISTR * myanpt;
long int * templpt;

	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= refsnum; myanpt--;
	insertoff = myanpt->anstartoff; insertoff-=4;
	templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);
	*templpt = frame*BLOCKSTRSIZE;
}

void DestroyUnusedGraphics (void)
{
int i, j, k;
BLKSTR * mystrpt;

	if (blockstrpt==NULL) return;
	if (blockgfxpt==NULL) return;
	for (i=(numblockgfx-1);i>0;i--)
	{
		j = 0;
		mystrpt = (BLKSTR *) blockstrpt;
		mystrpt += numblockstr;
		for (k=(numblockstr-1);k>=0;k--) {
			mystrpt--;
			if (mystrpt->bgoff==(i*blockwidth*blockheight*((blockdepth+1)/8))) j = 1;
			if (mystrpt->fgoff==(i*blockwidth*blockheight*((blockdepth+1)/8))) j = 1;
			if (mystrpt->fgoff2==(i*blockwidth*blockheight*((blockdepth+1)/8))) j = 1;
			if (mystrpt->fgoff3==(i*blockwidth*blockheight*((blockdepth+1)/8))) j = 1;
		}
		if (j==0) {
			RemoveBytes (blockgfxpt+(i*blockwidth*blockheight*((blockdepth+1)/8)),
			blockgfxpt+(numblockgfx*blockwidth*blockheight*((blockdepth+1)/8)),
			blockwidth*blockheight*((blockdepth+1)/8));
			numblockgfx--;
			mystrpt = (BLKSTR *) blockstrpt;
			for (k=0;k<numblockstr;k++) {
				if (mystrpt->bgoff==(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->bgoff = 0;
				if (mystrpt->fgoff==(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff = 0;
				if (mystrpt->fgoff2==(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff2 = 0;
				if (mystrpt->fgoff3==(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff3 = 0;
				if (mystrpt->bgoff>(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->bgoff -= (blockwidth*blockheight*((blockdepth+1)/8));
				if (mystrpt->fgoff>(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff -= (blockwidth*blockheight*((blockdepth+1)/8));
				if (mystrpt->fgoff2>(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff2 -= (blockwidth*blockheight*((blockdepth+1)/8));
				if (mystrpt->fgoff3>(i*blockwidth*blockheight*((blockdepth+1)/8)))
					mystrpt->fgoff3 -= (blockwidth*blockheight*((blockdepth+1)/8));
				mystrpt++;
			}
		}
	}
}

int ResizeMap (int neww, int newh, int mapc)
{
int i, j, k;
short int sxoff, syoff, dxoff, dyoff;
short int * temppt, * spt, * dpt;

	for (k=0;k<8;k++) { if (mapmappt[k] != NULL) {
		temppt = (short int *) malloc (neww*newh*2);
		if (temppt==NULL) return -1;
		memset (temppt, 0, neww*newh*2);

		sxoff = 0; syoff = 0; dxoff = 0; dyoff = 0;
		if ((mapc==1) || (mapc==4) || (mapc==7)) {
		sxoff = 0; dxoff = 0; }
		if ((mapc==3) || (mapc==6) || (mapc==9)) {
		dxoff = neww-mapwidth; if (dxoff<0) dxoff = 0;
		sxoff = mapwidth-neww; if (sxoff<0) sxoff = 0; }
		if ((mapc==2) || (mapc==5) || (mapc==8)) {
		dxoff = (neww-mapwidth)/2; if (dxoff<0) { sxoff = -dxoff; dxoff = 0; } }

		if ((mapc==1) || (mapc==2) || (mapc==3)) {
		syoff = 0; dyoff = 0; }
		if ((mapc==4) || (mapc==5) || (mapc==6)) {
		dyoff = (newh-mapheight)/2; if (dyoff<0) { syoff = -dyoff; dyoff = 0; } }
		if ((mapc==7) || (mapc==8) || (mapc==9)) {
		dyoff = newh-mapheight; if (dyoff<0) dyoff = 0;
		syoff = mapheight-newh; if (syoff<0) syoff = 0; }

		if (newh>mapheight) j = mapheight; else j = newh; while (j)
		{
			spt = mapmappt[k]; dpt = temppt;
			spt += sxoff; spt += syoff*mapwidth;
			dpt += dxoff; dpt += dyoff*neww;
			syoff++; dyoff++;
			if (neww>mapwidth) i = mapwidth; else i = neww;
			while (i)
			{
				*dpt = *spt; spt++; dpt++;
				i--;
			}
			j--;
		}
		free (mapmappt[k]); mapmappt[k] = temppt; } }

	mapwidth = neww; mapheight = newh; xmapoffset = 0; ymapoffset = 0;
	mappt = mapmappt[maplayer];
	return 0;
}

void FillwithPattern (int x, int y, int fstyle)
{
int i, j, mybrushwidth, mybrushheight, mybrshx, mybrshy, myinitx;
short int * mymappt, * mybrshpt;

	mybrushwidth = 0;
	mybrushheight = 0;
	mybrshx = 0;
	mybrshy = 0;
	myinitx = 0;
	mybrshpt = NULL;

	if (curbrsh>0 && curbrsh<=MAXBRSH) {
		if ((blockstaggerx || blockstaggery) && y&1) y--;
		mybrshpt = brshpt[curbrsh-1];
		if (brshpt==NULL) {
			curbrsh = 0; curanim = -1; curstr = 0;
		} else {
			mybrushwidth = *mybrshpt; mybrshpt++;
			mybrushheight = *mybrshpt; mybrshpt++;
			if (!fstyle) {
			mybrshx = (mybrushwidth-(x%mybrushwidth));
			if (mybrshx==mybrushwidth) mybrshx = 0;
			myinitx = mybrshx;
			mybrshy = (mybrushheight-(y%mybrushheight));
			if (mybrshy==mybrushheight) mybrshy = 0;
			mybrshpt += mybrshx+(mybrshy*mybrushwidth);
		} }
	}

	mymappt = mappt;
	for (j=0;j<mapheight;j++) {
		for (i=0;i<mapwidth;i++) {
			if (*mymappt==0x7fff) {
			if (curbrsh>0 && curbrsh<=MAXBRSH) {
				if (!fstyle) *mymappt = *mybrshpt;
				else *mymappt = mybrshpt[(rand()%mybrushwidth)+((rand()%mybrushheight)*mybrushwidth)];
			} else { if (curanim!=-1 && animstrpt!=NULL) {
				*mymappt = -((curanim+1)*sizeof(ANISTR));
			} else {
				*mymappt = (curstr);
			} } }
			mymappt++;
			if (curbrsh>0 && curbrsh<=MAXBRSH && !fstyle) { mybrshpt++; mybrshx++;
				if (mybrshx==mybrushwidth) { mybrshx = 0; mybrshpt -= mybrushwidth; }
			}
		}
		if (curbrsh>0 && curbrsh<=MAXBRSH && !fstyle) { mybrshpt -= mybrshx; mybrshx = myinitx; mybrshpt += myinitx;
			mybrshy++; mybrshpt += mybrushwidth;
			if (mybrshy==mybrushheight) { mybrshy = 0; mybrshpt -= (mybrushheight*mybrushwidth); }
		}
	}
}

void FillaLine (MAPFILL * myfillpt)
{
int i, j;
short int * fillmappt;

	fillmappt = mappt;
	fillmappt += myfillpt->yoff*mapwidth;

	i = (int) myfillpt->leftedge;
	j = (int) myfillpt->width;
	while (j) {
			fillmappt[i] = 0x7fff; /* Fill with 0x7fff so as not to continually overwrite... */
		i++; j--;
	}
}

short int AddaLine (MAPFILL * myfillpt, int fxoff, int fyoff, short int fillval)
{
short int filllength, returnfill;
short int * mymappt;

	if (fxoff<0 || fxoff>=mapwidth) return 1;
	if (fyoff<0 || fyoff>=mapheight) return 1;
	mymappt = mappt;
	mymappt += fyoff*mapwidth;
	if (fillval==-1) { fillval = mymappt[fxoff]; returnfill = fillval; } else returnfill = -1;
	if (mymappt[fxoff]!=fillval) return 1;

	while (myfillpt->leftedge!=-1) {
		if (myfillpt->leftedge==-2) { myfillpt++; myfillpt->leftedge=-2; myfillpt--; break; }
		myfillpt++;
	}

	while (fxoff>=0) { if (mymappt[fxoff]!=fillval) break; fxoff--; } fxoff++;
	myfillpt->yoff = (short int) fyoff;
	myfillpt->leftedge = (short int) fxoff;
	filllength = 0; while (fxoff<mapwidth)
		{ if (mymappt[fxoff]!=fillval) break; filllength++; fxoff++; }
	myfillpt->width = filllength;
	if (returnfill==-1) return filllength; else return returnfill;
}

void MapFill (int x, int y, int fillstyle)
{
int fillx, filly;
short int tofill, linestodo, checkxpos;
MAPFILL * mapfillpt, * thisfillpt;

	if (mappt==NULL) return;
	if (x<0 || x>=mapwidth) return;
	if (y<0 || y>=mapheight) return;

	mapfillpt = malloc (sizeof(MAPFILL)*10000);
	if (mapfillpt==NULL) return;
	mapfillpt->leftedge=-2;

	fillx = x; filly = y;
	tofill = AddaLine (mapfillpt, x, y, -1);

	while (1) {
		linestodo = 0;
		thisfillpt = mapfillpt; while (thisfillpt->leftedge!=-2) {
			if (thisfillpt->leftedge!=-1) {
				FillaLine (thisfillpt);
				checkxpos = thisfillpt->leftedge;
				while (checkxpos<(thisfillpt->leftedge+thisfillpt->width))
					checkxpos += AddaLine (mapfillpt, checkxpos, thisfillpt->yoff-1, tofill);
				checkxpos = thisfillpt->leftedge;
				while (checkxpos<(thisfillpt->leftedge+thisfillpt->width))
					checkxpos += AddaLine (mapfillpt, checkxpos, thisfillpt->yoff+1, tofill);
				thisfillpt->leftedge = -1;
				linestodo = 1;
			}
			thisfillpt++;
		}
		if (!linestodo) break;
	}
	free (mapfillpt);
	FillwithPattern (fillx, filly, fillstyle);
}

void RemoveSingleGraphic (int gnum)
{
int k;
BLKSTR * mystrpt;

	RemoveBytes (blockgfxpt+(gnum*blockwidth*blockheight*((blockdepth+1)/8)),
		blockgfxpt+(numblockgfx*blockwidth*blockheight*((blockdepth+1)/8)),
		blockwidth*blockheight*((blockdepth+1)/8));
	numblockgfx--;
	mystrpt = (BLKSTR *) blockstrpt;

	for (k=0;k<numblockstr;k++) {
		if (mystrpt->bgoff==(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->bgoff = 0;
		if (mystrpt->fgoff==(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff = 0;
		if (mystrpt->fgoff2==(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff2 = 0;
		if (mystrpt->fgoff3==(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff3 = 0;
		if (mystrpt->bgoff>(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->bgoff -= (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff>(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff -= (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff2>(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff2 -= (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff3>(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff3 -= (blockwidth*blockheight*((blockdepth+1)/8));
		mystrpt++;
	}
}

void InsertSingleGraphic (int gnum)
{
int k;
BLKSTR * mystrpt;

	InsertBytes (blockgfxpt+(gnum*blockwidth*blockheight*((blockdepth+1)/8)),
		blockgfxpt+((numblockgfx+1)*blockwidth*blockheight*((blockdepth+1)/8)),
		blockwidth*blockheight*((blockdepth+1)/8));
	numblockgfx++;
	mystrpt = (BLKSTR *) blockstrpt;

	for (k=0;k<numblockstr;k++) {
		if (mystrpt->bgoff>=(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->bgoff += (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff>=(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff += (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff2>=(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff2 += (blockwidth*blockheight*((blockdepth+1)/8));
		if (mystrpt->fgoff3>=(gnum*blockwidth*blockheight*((blockdepth+1)/8)))
			mystrpt->fgoff3 += (blockwidth*blockheight*((blockdepth+1)/8));
		mystrpt++;
	}
}

